Используя MS SQL Server, я хотел бы подсчитать количество сущностей, с которыми связана каждая из нескольких сущностей. Скажем, моя схема выглядит примерно так:

foo (
  id UNIQUEIDENTIFIER NOT NULL,
)

thing1 (
  id UNIQUEIDENTIFIER NOT NULL
)

thing2 (
  id UNIQUEIDENTIFIER NOT NULL
)

thingN (
  id UNIQUEIDENTIFIER NOT NULL
)

С объединенными таблицами

foo_thing1 (
  foo_id UNIQUEIDENTIFIER NOT NULL,
  thing1_id UNIQUEIDENTIFIER NOT NULL
)

И т.п.

Там может быть 2 штуки, или 10, или какое-то другое число - мне нужно что-то, что хорошо работает, даже когда их довольно много. Если бы был только один Foo, возможное решение выглядело бы так:

SELECT COUNT(DISTINCT foo_thing1.thing1_id),
       COUNT(DISTINCT foo_thing2.thing2_id),
       COUNT(DISTINCT foo_thing3.thing3_id),
       COUNT(DISTINCT foo_thing4.thing4_id,
FROM foo
LEFT JOIN foo_thing1 ON foo_thing1.thing1_id = thing1.id
LEFT JOIN foo_thing2 ON foo_thing2.thing2_id = thing2.id
LEFT JOIN foo_thing3 ON foo_thing3.thing3_id = thing3.id
LEFT JOIN foo_thing4 ON foo_thing4.thing4_id = thing4.id
GROUP BY foo.id
HAVING foo.id = '12341234-1234-12341234-1234'

Однако я не уверен, что это эффективно. Что, если Foo относится ко многим вещам thing2 и очень много thing3 - я получаю слишком много строк, а затем скрываю их с помощью DISTINCT?

Еще больше усложняя ситуацию, я на самом деле хочу посчитать отношения более чем одного foo одновременно. В идеале я бы хотел сделать это произвольным предложением where, но при необходимости я могу просто предоставить список идентификаторов, таких как WHERE / HAVING foo.id IN (x, y, z). Но как оттуда определить все мощности? :(

UNION ALL - это один из вариантов, поскольку моя цель при объединении этих запросов - уменьшить задержку при передаче данных в оба конца. Но я подозреваю, что время синтаксического анализа нескольких SELECT означает, что это не может быть самым наиболее эффективным способом ...

0
banana 5 Янв 2014 в 21:49
Привет. Возможно, это дубликат stackoverflow.com/questions/2855373/sql- отдельный-выбор-сервера?
 – 
Mike M
5 Янв 2014 в 23:01
Не совсем то же самое, нет. Этот плакат хочет подсчитать упорядоченные столбцы для одного объекта.
 – 
banana
5 Янв 2014 в 23:03
Конечно. Мне понравилась возможность находить эти Отличные пары (или тройки и т. Д.). Так что лучше сказать, что вы хотите найти все пары автоматически, не зная их заранее?
 – 
Mike M
6 Янв 2014 в 03:07

1 ответ

Лучший ответ

Это должно работать так, как вы ожидаете:

SELECT foo.id,
    (SELECT count(*) FROM foo_thing1 WHERE foo_thing1.foo_id = foo.id),
    (SELECT count(*) FROM foo_thing2 WHERE foo_thing2.foo_id = foo.id),
    (SELECT count(*) FROM foo_thing3 WHERE foo_thing3.foo_id = foo.id),
    ...
FROM foo
WHERE foo.id IN (1, 2, 3, 7, ...);
1
Gordon Linoff 6 Янв 2014 в 01:14
Это выглядит многообещающе! Попробую завтра, когда пойду на работу, и приму ответ. Есть ли какие-нибудь интересные предостережения относительно использования здесь подзапросов?
 – 
banana
5 Янв 2014 в 23:06
Надеюсь, вы проиндексировали эти столбцы foo_thingN.foo_id, иначе запрос будет очень медленным. Кроме этого, у вас не должно возникнуть никаких проблем.
 – 
Kombajn zbożowy
6 Янв 2014 в 13:34
Да, они проиндексированы. Запрос оказался успешным.
 – 
banana
16 Янв 2014 в 18:32