группировать, подсчитывать и присоединяться

У меня есть 3 таблицы, которые выглядят примерно так:

Таблица1 Пользователи:

  • ID
  • Имя
  • Счет

Table2 Game:

  • ID
  • Имя
  • Фолы

Таблица 3 Game2

  • ID
  • Имя
  • Фолы

Что я хотел бы сделать, так это в Таблице 1 выбрать всех пользователей. Затем выберите все данные, в которых Table1.Name = Table2.Name OR Table1.Name = Table3.Name, но с более высоким приоритетом, чем Table2, поэтому, если есть соответствие Table1.Name = Table2.Name, соединение из таблицы 3 не будет выполнено. Затем, когда я выбрал правильный, я также хотел бы посчитать общую сумму очков и фолов.

Как это делается в SQL и возможно ли это? Я использую MSSQL


person Mikael    schedule 13.05.2011    source источник


Ответы (2)


Вы можете отдать предпочтение объединению с таблицей 2, указав в условии соединения с таблицей 3 Table2.Name IS NULL. Если бы вы хотели получить общий счет и количество фолов для каждого игрока, вот как бы вы это сделали:

SELECT derived_table.Name, SUM(derived_table.Score), SUM(derived_table.Fouls)
FROM (
    SELECT Name = Table1.Name, Score = Table1.Score,
        Fouls = COALESCE(Table2.Fouls, Table3.Fouls)
    FROM Table1
        LEFT OUTER JOIN Table2 ON Table2.Name = Table1.Name
        LEFT OUTER JOIN Table3 ON Table3.Name = Table1.Name
            AND Table2.Name IS NULL
    WHERE Table2.Name IS NOT NULL OR Table3.Name IS NOT NULL
    ) derived_table
GROUP BY derived_table.Name

Итого:

SELECT SUM(derived_table.Score), SUM(derived_table.Fouls)
FROM (
    SELECT Score = Table1.Score,
        Fouls = COALESCE(Table2.Fouls, Table3.Fouls)
    FROM Table1
        LEFT OUTER JOIN Table2 ON Table2.Name = Table1.Name
        LEFT OUTER JOIN Table3 ON Table3.Name = Table1.Name
            AND Table2.Name IS NULL
    WHERE Table2.Name IS NOT NULL OR Table3.Name IS NOT NULL
    ) derived_table
person Jake T.    schedule 13.05.2011

Ниже приведено многое из того, что вам нужно. Я не уверен, хотите ли вы агрегировать на пользователя или в целом.

Кроме того, если у вас будет Game3, Game4 и т. Д., То лучше всего изменить дизайн таблицы, а не усложнять этот (и другие) запросы.

SELECT      SUM(U.Score) AS Score,
        SUM(Fouls.Fouls) AS Fouls
FROM        dbo.Users U
INNER JOIN  (
    SELECT      COALESCE(G.Name, G2.Name) AS Name,
            COALESCE(G.Fouls, G2.Fouls) AS Fouls
    FROM        dbo.Game G
    FULL JOIN   dbo.Game2 G2
    ON      G.Name = G2.Name
) Fouls
ON      U.Name = Fouls.Name
person Will A    schedule 13.05.2011
comment
Я не хочу агрегировать по пользователям. Я ищу общий, тогда это сработает? Сложность хочу пойти дальше, но я понимаю вашу точку зрения. - person Mikael; 13.05.2011
comment
@Mikael - попробуйте это, посмотрите, даст ли это вам то, что вы хотите. Если агрегаты не совсем правильные, для их сортировки используется GROUP BY. - person Will A; 13.05.2011
comment
Да, это работает, но теперь мне нужно подсчитать общее количество фолов и очков, как мне применить GROUP BY и COUNT () - person Mikael; 13.05.2011
comment
@Mikael - вы бы предпочли использовать SUM, и, поскольку вы не хотите группировать по пользователям, вы можете опустить предложение GROUP BY. Я обновил свой T-SQL. - person Will A; 13.05.2011