Упорядочить SQL-запрос по сумме определенных столбцов

#sql #sql-server #sql-server-2005

#sql #sql-сервер #sql-server-2005

Вопрос:

Вот выдержка из довольно большой таблицы (SQL Server 2005), к которой я запрашиваю:

 id (primary key) |  account  |  phone  |  employee  | address
------------------------------------------------------------------
1                |   123     |    Y    |    Y       |   N
2                |   456     |    N    |    N       |   N
3                |   789     |    Y    |    Y       |   Y
  

Мне нужно возвращать только те строки, в которых есть хотя бы один Y в phone, employee или address (здесь не показано около 10 других). Затем мне нужно упорядочить эти результаты по количеству Y, которые у них есть в любом из трех.

Я попытался получить «tagTotal» следующим образом:

 SELECT
SUM(
  CASE WHEN [phone] = 'Y' THEN 1 ELSE 0 END
    CASE WHEN [employee] = 'Y' THEN 1 ELSE 0 END
    CASE WHEN [address] = 'Y' THEN 1 ELSE 0 END
  )
  FROM table
  GROUP BY id
  

это возвращает:

 tagTotal
---------------
2
0
3
  

Я в недоумении, как объединить это с моим существующим гигантским запросом и упорядочить по нему, не добавляя каждый столбец в группу by в конце.

Комментарии:

1. ВЫПОЛНИТЕ встроенную сумму, поскольку вам не нужно суммировать по строкам.

Ответ №1:

Поскольку сумма значений, которые вам нужны, находится в одной строке, вам не нужно объединять результаты, тем самым устраняя необходимость в group by ..

 SELECT
CASE WHEN [phone] = 'Y' THEN 1 ELSE 0 END    
CASE WHEN [employee] = 'Y' THEN 1 ELSE 0 END    
CASE WHEN [address] = 'Y' THEN 1 ELSE 0 END as Total
FROM table
  

Ответ №2:

Вы можете просто выполнить добавление в виде столбца, а затем упорядочить результаты. Агрегирование кажется ненужным, по крайней мере, с образцами данных в вопросе. Для каждого есть только одна строка id .

 SELECT t.*
FROM (SELECT t.*,
             ((CASE WHEN [phone] = 'Y' THEN 1 ELSE 0 END)  
              (CASE WHEN [employee] = 'Y' THEN 1 ELSE 0 END)  
              (CASE WHEN [address] = 'Y' THEN 1 ELSE 0 END)
             ) as NumYs
      FROM table t
     ) t
WHERE NumYs > 0
ORDER BY NumYs DESC;
  

Ответ №3:

Попробуйте выбрать идентификатор и упорядочить по сумме?

 SELECT id, 
SUM(
  CASE WHEN [phone] = 'Y' THEN 1 ELSE 0 END
    CASE WHEN [employee] = 'Y' THEN 1 ELSE 0 END
    CASE WHEN [address] = 'Y' THEN 1 ELSE 0 END
  ) as numsum
  FROM table
  ORDER BY numsum
  

Ответ №4:

Это должно сработать:

 select *
from
(
    SELECT
       id, 
       SUM(
           CASE WHEN [phone] = 'Y' THEN 1 ELSE 0 END
             CASE WHEN [employee] = 'Y' THEN 1 ELSE 0 END
             CASE WHEN [address] = 'Y' THEN 1 ELSE 0 END
          ) tagTotal
  FROM table
  GROUP BY id
) x
where x.tagTotal <> 0
order by x.tagTotal desc
  

Внутренний запрос в основном ваш, с добавлением идентификатора (который, я полагаю, вам нужен) и присвоением сумме имени. Затем это используется в качестве входных данных для внешнего запроса, исключая запросы с нулевым итогом и сортируя сначала с наибольшей суммой.

(Кстати, это небольшой запрос. Самая большая инструкция select, которую я написал, занимала более 250 строк, выполнялась за 20 минут и выполняла ежедневные отчеты о прибылях и убытках компании, занимающейся торговлей сырьевыми товарами. Это было много …)