Вопрос по группировке SQL - PullRequest
2 голосов
/ 19 марта 2010

Я пытаюсь добиться следующего без использования подзапроса.

Для финансирования я хотел бы выбрать дату создания последнего письма и «самый ранний рабочий список, созданный с момента создания письма» для финансирования.

FundingId Leter (1, 1/1/2009 )(1, 5/5/2009) (1, 8/8/2009) (2, 3/3/2009) 

FundingId WorkList (1, 5/5/2009 ) (1, 9/9/2009) (1, 10/10/2009) (2, 2/2/2009) 

Ожидаемый результат -

FundingId Leter WorkList (1, 8/8/2009, 9/9/2009)

Я написал запрос следующим образом. Это ошибка. Он пропустит те FundingId, для которых минимальная дата WorkList меньше последней даты Letter (даже если у него есть другой рабочий список с датой создания, превышающей букву).

CREATE TABLE #Funding(
[Funding_ID] [int] IDENTITY(1,1) NOT NULL,
[Funding_No] [int] NOT NULL,
CONSTRAINT [PK_Center_Center_ID] PRIMARY KEY NONCLUSTERED ([Funding_ID] ASC)
) ON [PRIMARY]

CREATE TABLE #Letter(
[Letter_ID] [int] IDENTITY(1,1) NOT NULL,
[Funding_ID] [int] NOT NULL,
[CreatedDt] [SMALLDATETIME],
CONSTRAINT [PK_Letter_Letter_ID] PRIMARY KEY NONCLUSTERED ([Letter_ID] ASC)
) ON [PRIMARY]

CREATE TABLE #WorkList(
[WorkList_ID] [int] IDENTITY(1,1) NOT NULL,
[Funding_ID] [int] NOT NULL,
[CreatedDt] [SMALLDATETIME],
CONSTRAINT [PK_WorkList_WorkList_ID] PRIMARY KEY NONCLUSTERED ([WorkList_ID] ASC)
) ON [PRIMARY]

SELECT F.Funding_ID,
Funding_No, 
MAX (L.CreatedDt),
MIN(W.CreatedDt)
FROM #Funding F
INNER JOIN #Letter L ON L.Funding_ID = F.Funding_ID
LEFT OUTER JOIN #WorkList W ON W.Funding_ID = F.Funding_ID
GROUP BY F.Funding_ID,Funding_No
HAVING MIN(W.CreatedDt) > MAX (L.CreatedDt)

Как написать правильный запрос без использования подзапроса?

Пожалуйста, помогите

Спасибо

Lijo

Ответы [ 2 ]

1 голос
/ 19 марта 2010

использование производных таблиц так же хорошо, как это получается:

Таблицы ОП:

CREATE TABLE #Funding(
[Funding_ID] [int] IDENTITY(1,1) NOT NULL,
[Funding_No] [int] NOT NULL,
CONSTRAINT [PK_Center_Center_ID] PRIMARY KEY NONCLUSTERED ([Funding_ID] ASC)
) ON [PRIMARY]

CREATE TABLE #Letter(
[Letter_ID] [int] IDENTITY(1,1) NOT NULL,
[Funding_ID] [int] NOT NULL,
[CreatedDt] [SMALLDATETIME],
CONSTRAINT [PK_Letter_Letter_ID] PRIMARY KEY NONCLUSTERED ([Letter_ID] ASC)
) ON [PRIMARY]

CREATE TABLE #WorkList(
[WorkList_ID] [int] IDENTITY(1,1) NOT NULL,
[Funding_ID] [int] NOT NULL,
[CreatedDt] [SMALLDATETIME],
CONSTRAINT [PK_WorkList_WorkList_ID] PRIMARY KEY NONCLUSTERED ([WorkList_ID] ASC)
) ON [PRIMARY]

Данные образца OP:

INSERT INTO #Funding (Funding_No) VALUES (1)
INSERT INTO #Funding (Funding_No) VALUES (2)

INSERT INTO #Letter (Funding_ID,CreatedDt) VALUES (1,'1/1/2009')
INSERT INTO #Letter (Funding_ID,CreatedDt) VALUES (1,'5/5/2009')
INSERT INTO #Letter (Funding_ID,CreatedDt) VALUES (1,'8/8/2009')
INSERT INTO #Letter (Funding_ID,CreatedDt) VALUES (2,'3/3/2009')

INSERT INTO #WorkList (Funding_ID,CreatedDt) VALUES (1, '5/5/2009')
INSERT INTO #WorkList (Funding_ID,CreatedDt) VALUES (1, '9/9/2009')
INSERT INTO #WorkList (Funding_ID,CreatedDt) VALUES (1, '10/10/2009')
INSERT INTO #WorkList (Funding_ID,CreatedDt) VALUES (2, '2/2/2009')

Таблица CREATE выглядит как TSQL, но версия не указана, поэтому CTE также можно было использовать. Однако для этого используются производные таблицы:

SELECT
    dt.Funding_ID,LCreatedDt,MIN(CreatedDt) AS WCreatedDt
    FROM (SELECT
              f.Funding_Id,l.LCreatedDt
              FROM #Funding    f
              LEFT OUTER JOIN (SELECT
                                   Funding_ID,MAX(CreatedDt) AS LCreatedDt
                                   FROM #Letter
                                   GROUP BY Funding_ID
                              ) l ON f.Funding_ID=l.Funding_ID
         ) dt
    LEFT OUTER JOIN #WorkList w ON dt.Funding_ID=w.Funding_ID
    WHERE w.CreatedDt>dt.LCreatedDt
    GROUP BY dt.Funding_ID,LCreatedDt

ВЫВОД:

Funding_ID  LCreatedDt              WCreatedDt
----------- ----------------------- -----------------------
1           2009-08-08 00:00:00     2009-09-09 00:00:00

(1 row(s) affected)

чтобы опередить всех, кто утверждает, что мой запрос использует подзапрос, сначала прочтите эту статью Основы подзапроса: http://msdn.microsoft.com/en-us/library/aa213252(SQL.80).aspx

Подзапрос - это запрос SELECT, который возвращает одно значение и является вложенным внутри SELECT, INSERT, UPDATE или УДАЛИТЬ оператор или внутри другого подзапрос. Подзапрос может быть использован везде, где разрешено выражение.

1 голос
/ 19 марта 2010

Ваш вопрос How can I write a correct query without using subquery?

Но вы не используете подзапрос ... поэтому у вас уже есть ответ.

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