Получить отличные результаты из базы данных, которая имеет «словарь» - PullRequest
0 голосов
/ 20 апреля 2020

У меня есть база данных со «словарем», подобным этому:

Id (INT) | Key (VARCHAR) | Value (VALUE) | ForeignKey (INT?)
------------------------------------------------------------
1        | foo           | bar           | 23
2        | bar           | foo           | NULL
3        | foobar        | value         | NULL
4        | foobar        | othervalue    | 47

Теперь я хочу получить все ключи и значения для указанного c внешнего ключа, но также все внешние ключи, которые имеют значение NULL. , так что результат выглядит так:

ForeignKey = 23:           ForeignKey = 47:

foo    | bar               bar    | foo
bar    | foo               foobar | othervalue
foobar | value

Первоначально я попробовал этот подход:

dbContext.Table
    .Where(t => t.ForeignKey == 47 || t.ForeignKey == null)

, но это дает мне foobar дважды.

Я тогда хотя о множественных запросах и объединении результатов:

var t1 = _dbContext.Table
    .Where(t => t.ForeignKey == 47);

var t2 = _dbContext.Table
    .Where(t => t.ForeignKey == null && !t1.Any(tt => tt.Key == t.Key));

var final = t1.Union(t2);

Это, похоже, работает, но создает это SQL (примерно), которое кажется чрезмерным с тремя SELECT, тремя WHERE и UNION

SELECT [t1].[Id], [t1].[Key], [t1].[Value], [t1].ForeignKey
FROM [Table] AS [t1]
WHERE [t1].[ForeignKey] = 47
UNION
SELECT [t2].[Id], [t2].[Key], [t2].[Value], [t2].ForeignKey
FROM [Table] AS [t2]
WHERE [t2].[ForeignKey] IS NULL AND NOT (EXISTS (
    SELECT 1
    FROM [Table] AS [t3]
    WHERE ([t3].[ForeignKey] = 47) AND ([t3].[Key] = [t2].[Key])))

У меня просто внутреннее чувство, что "должен быть лучший путь" ... так, есть? Как получить ключи и значения для указанного внешнего ключа c, а также ключи, которые еще не получены, которые имеют значение NULL?

1 Ответ

1 голос
/ 20 апреля 2020

SQL, который вы видите, не кажется мне чрезмерным. Если вы не проверили это и не обнаружили неприемлемо плохую производительность, я бы не стал тратить слишком много времени на его оптимизацию.

Однако есть альтернативный подход, который может быть предпочтительнее. Вам нужно провести некоторое тестирование, чтобы увидеть, дает ли оно лучшее SQL, план выполнения и производительность. В основном, я бы go с таким подходом было бы легче понять другим разработчикам.

var final = dbContext.Table.Where(t => t.ForeignKey == 47 || t.ForeignKey == null)
    .GroupBy(t => t.Key)
    .Select(g => g.OrderBy(t => t.ForeignKey == null ? 1 : 0).FirstOrDefault());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...