Как я могу сделать столбцы "месяц" в Sql? - PullRequest
6 голосов
/ 19 февраля 2010

У меня есть набор данных, который выглядит примерно так ( ОЧЕНЬ упрощенно):

productId    Qty   dateOrdered
---------    ---   -----------
       1       2    10/10/2008
       1       1    11/10/2008
       1       2    10/10/2009
       2       3    10/12/2009
       1       1    10/15/2009
       2       2    11/15/2009

Из этого мы пытаемся создать запрос, чтобы получитьчто-то вроде:

productId  Year  Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
---------  ----  --- --- --- --- --- --- --- --- --- --- --- ---
        1  2008    0   0   0   0   0   0   0   0   0   2   1   0
        1  2009    0   0   0   0   0   0   0   0   0   3   0   0
        2  2009    0   0   0   0   0   0   0   0   0   3   2   0

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

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

(Я использую MS Sql Server, поэтому ответы, специфичные для этой БД, подойдут.)

(Я только начинаю искатьв «PIVOT» в качестве возможной помощи, но я пока ничего об этом не знаю, поэтому, если кто-то захочет это прокомментировать, это также может быть полезно.)

Ответы [ 5 ]

10 голосов
/ 10 декабря 2013
select productId, Year(dateOrdered) Year
  ,isnull(sum(case when month(dateOrdered) = 1 then Qty end), 0) Jan
  ,isnull(sum(case when month(dateOrdered) = 2 then Qty end), 0) Feb 
  ,isnull(sum(case when month(dateOrdered) = 3 then Qty end), 0) Mar
  ,isnull(sum(case when month(dateOrdered) = 4 then Qty end), 0) Apr
  ,isnull(sum(case when month(dateOrdered) = 5 then Qty end), 0) May
  ,isnull(sum(case when month(dateOrdered) = 6 then Qty end), 0) Jun
  ,isnull(sum(case when month(dateOrdered) = 7 then Qty end), 0) Jul
  ,isnull(sum(case when month(dateOrdered) = 8 then Qty end), 0) Aug
  ,isnull(sum(case when month(dateOrdered) = 9 then Qty end), 0) Sep
  ,isnull(sum(case when month(dateOrdered) = 10 then Qty end), 0) Oct
  ,isnull(sum(case when month(dateOrdered) = 11 then Qty end), 0) Nov
  ,isnull(sum(case when month(dateOrdered) = 12 then Qty end), 0) Dec
from Table1
group by productId, Year(dateOrdered)

SQL Fiddle

1 голос
/ 22 февраля 2013
SELECT productId, YEAR,
ISNULL((SELECT SUM(Qty) FROM Product WHERE productId=X.productId AND YEAR=YEAR(dateOrdered) AND MONTH(dateOrdered)=1),0) as 'JAN',
ISNULL((SELECT SUM(Qty) FROM Product WHERE productId=X.productId AND YEAR=YEAR(dateOrdered) AND MONTH(dateOrdered)=2),0) as 'FEB',
ISNULL((SELECT SUM(Qty) FROM Product WHERE productId=X.productId AND YEAR=YEAR(dateOrdered) AND MONTH(dateOrdered)=3),0) as 'MAR',
ISNULL((SELECT SUM(Qty) FROM Product WHERE productId=X.productId AND YEAR=YEAR(dateOrdered) AND MONTH(dateOrdered)=4),0) as 'APR',
ISNULL((SELECT SUM(Qty) FROM Product WHERE productId=X.productId AND YEAR=YEAR(dateOrdered) AND MONTH(dateOrdered)=5),0) as 'MAY',
ISNULL((SELECT SUM(Qty) FROM Product WHERE productId=X.productId AND YEAR=YEAR(dateOrdered) AND MONTH(dateOrdered)=6),0) as 'JUN',
ISNULL((SELECT SUM(Qty) FROM Product WHERE productId=X.productId AND YEAR=YEAR(dateOrdered) AND MONTH(dateOrdered)=7),0) as 'JUL',
ISNULL((SELECT SUM(Qty) FROM Product WHERE productId=X.productId AND YEAR=YEAR(dateOrdered) AND MONTH(dateOrdered)=8),0) as 'AUG',
ISNULL((SELECT SUM(Qty) FROM Product WHERE productId=X.productId AND YEAR=YEAR(dateOrdered) AND MONTH(dateOrdered)=9),0) as 'SEP',
ISNULL((SELECT SUM(Qty) FROM Product WHERE productId=X.productId AND YEAR=YEAR(dateOrdered) AND MONTH(dateOrdered)=10),0) as 'OCT',
ISNULL((SELECT SUM(Qty) FROM Product WHERE productId=X.productId AND YEAR=YEAR(dateOrdered) AND MONTH(dateOrdered)=11),0) as 'NOV',
ISNULL((SELECT SUM(Qty) FROM Product WHERE productId=X.productId AND YEAR=YEAR(dateOrdered) AND MONTH(dateOrdered)=12),0) as 'DEC'
FROM (
SELECT productId, YEAR(dateOrdered) AS YEAR FROM Product
GROUP BY YEAR(dateOrdered),ProductId) X
0 голосов
/ 08 февраля 2015

попробуйте это. Таким образом, этот код выберет данные за определенный промежуток времени, а затем преобразует их в новый столбец. Например, в моем коде sql: он выбирает диапазон времени между «2014-10-01» и «2014-10-31» из столбца «L_dt», затем создает новый столбец с именем «October». Таким образом, мы можем размещать данные в разных столбцах из одного столбца.

select 
sum(case when L_dt between '2014-10-01' and '2014-10-31' then 1 else 0 end) October,
sum(case when L_dt between '2014-11-01' and '2014-11-30' then 1 else 0 end) November,
sum(case when L_dt between '2014-12-01' and '2014-12-31' then 1 else 0 end) December
from Table; 

Если вход выглядит так: L_dt
2014-10-13 2014-12-21 2014-11-22 2014-10-10

Тогда вывод будет

+---------+----------+----------+
| October | November | December |
+---------+----------+----------+
|    2    |    1     |    1     |
+---------+----------+----------+
0 голосов
/ 14 марта 2010

Это квалифицируется как проблема представления.
Представление и SQL не всегда хорошо сочетаются.

Изоляция логики представления на уровне приложений позволит:

  1. сэкономить ваше время обслуживания - изменить код приложения, но сохранить SQL-код без изменений;
  2. позволит вам быстрее адаптироваться к эфемерным требованиям клиента;
  3. даст вам больше удовлетворения, чем возиться с кросс-таблицей или сводной таблицей, которая безумно делает почти то, что вы хотите.Python (вы можете использовать отличный модуль pyodbc для подключения к SQL Server):
    from collections import defaultdict
    from datetime import date
    
    dd = defaultdict(int)
    
    # input 
    rows = [(1,2,date(2008,10,10)), (1,1,date(2008,11,10)), 
            (1,2,date(2009,10,10)), (2,3,date(2009,10,12)), 
            (1,1,date(2009,10,15)), (2,2,date(2009,11,15))]
    
    for row in rows:
        # row[0] == productId
        # row[1] == Qty
        # row[2] == dateOrdered
        # pyodbc enables referring to column names by name
        dd[(row[2].year, row[2].month, row[0])] += row[1]
    
    presentation_rows = sorted(set((i[0], i[2]) for i in dd.keys()))
    
    for i in presentation_rows:
      print i[1], i[0], 
      for j in range(0,13):
        try:
          print dd[i[0], j, i[1]], 
        except IndexError:
          print 0,
      print
    
    # output
    # 1 2008 0 0 0 0 0 0 0 0 0 0 2 1 0
    # 1 2009 0 0 0 0 0 0 0 0 0 0 3 0 0
    # 2 2009 0 0 0 0 0 0 0 0 0 0 3 2 0
    
0 голосов
/ 19 февраля 2010

Вы можете использовать либо объединение ваших запросов, а не временные таблицы, либо использовать опцию pivot.

Вот обсуждение на форуме:

Форумы сервера Sql - Показатьпострочные данные в виде столбцов

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...