2016-06-27 6 views
-1

Ich habe zwei Abfragen zu tun, wie untenWie Vereinigung mehrerer CTE

Abfrage 1

set @sql = cast(N' 
;with cteSales as 
(
    select 
    datepart(weekday, s.enddate) as SalesWeekDay, 
    datediff(hour, cast(s.enddate as date), s.enddate) DayTime, 
    s.enddate SalesDate, 
    CONVERT(DECIMAL(10,2),OrigionalSubTotal/100.0) as OrigionalSubTotal, 
    o.ordertype ordertype 
    from sale s,DinePointOrderType o 
    where s.enddate >= @DateBegin and s.enddate < @DateEnd 
and o.ordertypeindex = s.ordertype 
and s.ordertype = 1 
    and s.IsSuspend = 0 and s.IsTrainMode = 0 
    and s.IsCancelled = 0 and s.wasrefunded=0 
), 
cteSalesPerWeekDays as 
(
    select 
    p.hrs, 
    p.period, 
    isnull(p.ordertype,''DINE IN'') ordertype,' as nvarchar(max)) + @col_per_day_list + N' 
    from #Timing t 
    cross join #WeekDays w 
    left join cteSales s on datediff(hour, w.wd_date, s.SalesDate) = t.hrs 
    pivot 
    (
    Sum(s.OrigionalSubTotal) 
    for w.wd_name in (' + @pivot_val_per_day_list + N') 
) p 
) 

select 
    r.hrs, 
    r.period as [From-To], 
    r.ordertype,' + @sum_cols_per_day_list + N' 
from cteSalesPerWeekDays r 
group by r.hrs, r.period,r.ordertype 
order by r.hrs 

' 
exec sp_executesql @sql, N'@DateBegin datetime, @DateEnd datetime', 
    @DateBegin = @DateBegin, 
    @DateEnd = @TradeDateEnd 

GO 

Abfrage 2

set @sql = cast(N' 
;with cteSales as 
(
    select 
    datepart(weekday, s.enddate) as SalesWeekDay, 
    datediff(hour, cast(s.enddate as date), s.enddate) DayTime, 
    s.enddate SalesDate, 
    CONVERT(DECIMAL(10,2),OrigionalSubTotal/100.0) as OrigionalSubTotal, 
    o.ordertype ordertype 
    from sale s,DinePointOrderType o 
    where s.enddate >= @DateBegin and s.enddate < @DateEnd 
and o.ordertypeindex = s.ordertype 
and s.ordertype = 2 
    and s.IsSuspend = 0 and s.IsTrainMode = 0 
    and s.IsCancelled = 0 and s.wasrefunded=0 
), 
cteSalesPerWeekDays as 
(
    select 
    p.hrs, 
    p.period, 
    isnull(p.ordertype,''TAKE OUT'') ordertype,' as nvarchar(max)) + @col_per_day_list + N' 
    from #Timing t 
    cross join #WeekDays w 
    left join cteSales s on datediff(hour, w.wd_date, s.SalesDate) = t.hrs 
    pivot 
    (
    Sum(s.OrigionalSubTotal) 
    for w.wd_name in (' + @pivot_val_per_day_list + N') 
) p 
) 

select 
    r.hrs, 
    r.period as [From-To], 
    r.ordertype,' + @sum_cols_per_day_list + N' 
from cteSalesPerWeekDays r 
group by r.hrs, r.period,r.ordertype 
order by r.hrs 

' 


exec sp_executesql @sql, N'@DateBegin datetime, @DateEnd datetime', 
    @DateBegin = @DateBegin, 
    @DateEnd = @TradeDateEnd 

Ist es möglich, eine Vereinigung zu tun diese zwei Abfragen?

+0

Post Versuch, die UNION auszuführen, und welche Fehler Sie bekommen, so dass wir debug helfen deine Anstrengung. –

+0

@TabAlleman hat meine Frage bearbeitet – Sachu

+0

Der Grund für den Fehler ist, dass Sie Ihre erste 'CAST (' Funktion nach ''' Dine In''' schließen. Und Sie öffnen keine andere für' '' Take Out '' ' –

Antwort

0

So viel Code ... das könnte man einfach mit PIVOT und dynamischem SQL machen.

Erstellen von Tabellen Ausgabe testen:

CREATE TABLE #Ordertypes (
    ordertype_id int, 
    name nvarchar(10) 
) 

INSERT INTO #Ordertypes VALUES 
(1, 'DINE IN'), 
(2, 'TAKE OUT'), 
(3, 'DELIVERY') 


CREATE TABLE #Sale (
    StartDate datetime, 
    Amt money, 
    ordertype_id int 
) 

INSERT INTO #Sale VALUES 
('2016-06-12 10:01:15.780', 10.00, 1), 
('2016-06-12 10:15:57.360', 20.00, 1), 
('2016-06-12 12:48:41.250', 50.00, 2), 
('2016-06-13 12:04:45.090', 15.00, 3) 

CREATE TABLE #time_intervals (
    tStart time, 
    tEnd time 
) 

;WITH time_intervals AS (
SELECT CAST('00:00:00' as time) as tStart, 
     CAST('00:59:59' as time) as tEnd 
UNION ALL 
SELECT DATEADD(hour,1,tStart), 
     DATEADD(hour,1,tEnd) 
FROM time_intervals 
WHERE tEnd < CAST('23:59:59' as time) 
) 

INSERT INTO #time_intervals 
SELECT * 
FROM time_intervals 

Haupt query:

DECLARE @dateFrom date = '2016-06-12', 
     @dateTo date = '2016-06-13' 

DECLARE @sql nvarchar(max), 
     @columns nvarchar(max), 
     @cast_columns nvarchar(max) 

SELECT @cast_columns= STUFF((
    SELECT DISTINCT ',ISNULL(' + QUOTENAME(CAST(StartDate as date)) +',0.00) as ' + QUOTENAME(CAST(StartDate as date)) 
    FROM #Sale 
    WHERE CAST(StartDate as date) between @dateFrom and @dateTo 
    FOR XML PATH('')),1,1,''), 
    @columns = STUFF((
    SELECT DISTINCT ',' + QUOTENAME(CAST(StartDate as date)) 
    FROM #Sale 
    WHERE CAST(StartDate as date) between @dateFrom and @dateTo 
    FOR XML PATH('')),1,1,'') 

SELECT @sql = ' 
SELECT LEFT(tStart,5) + ''-'' + LEFT(DATEADD(second,1,tEnd),5) as Interval, 
     Name, 
     '[email protected]_columns+' 
FROM (
    SELECT tStart, 
      tEnd, 
      ot.name, 
      CAST(StartDate as date) as sDate, 
      Amt 
    FROM #time_intervals t 
    CROSS JOIN #Ordertypes ot 
    LEFT JOIN #Sale s 
     ON CAST(s.StartDate as time) between t.tStart and t.tEnd and ot.ordertype_id = S.ordertype_id 
) as p 
PIVOT (
    SUM(Amt) FOR sDate IN ('[email protected]+') 
) as pvt 
ORDER BY Name, tStart' 

EXEC sp_executesql @sql 

Ausgang:

Interval Name  2016-06-12 2016-06-13 
00:00-01:00 DELIVERY 0.00  0.00 
01:00-02:00 DELIVERY 0.00  0.00 
02:00-03:00 DELIVERY 0.00  0.00 
03:00-04:00 DELIVERY 0.00  0.00 
04:00-05:00 DELIVERY 0.00  0.00 
05:00-06:00 DELIVERY 0.00  0.00 
06:00-07:00 DELIVERY 0.00  0.00 
07:00-08:00 DELIVERY 0.00  0.00 
08:00-09:00 DELIVERY 0.00  0.00 
09:00-10:00 DELIVERY 0.00  0.00 
10:00-11:00 DELIVERY 0.00  0.00 
11:00-12:00 DELIVERY 0.00  0.00 
12:00-13:00 DELIVERY 0.00  15.00 
13:00-14:00 DELIVERY 0.00  0.00 
... 
09:00-10:00 DINE IN  0.00  0.00 
10:00-11:00 DINE IN  30.00  0.00 
11:00-12:00 DINE IN  0.00  0.00 
... 
11:00-12:00 TAKE OUT 0.00  0.00 
12:00-13:00 TAKE OUT 50.00  0.00 
13:00-14:00 TAKE OUT 0.00  0.00 
14:00-15:00 TAKE OUT 0.00  0.00 
1

Sie benötigen eine neue CAST auf dieser Linie zu starten:

isnull(p.ordertype,''DINE IN'') ordertype,' as nvarchar(max)) + @col_per_day_list + N' 

So:

isnull(p.ordertype,''DINE IN'') ordertype,' as nvarchar(max)) + @col_per_day_list + CAST(N' 

EDIT, und jetzt mit, dass Fehler behoben, ist Ihre UNION an der falschen Stelle.

Sie können nicht UNION zwei CTE wie folgt aus:

cteSalesPerWeekDays as 
(...) 
union 
cteSales as 
(...) 

Sie können nur UNION zwischen zwei SELECT-Anweisungen verwenden. So könnte man Dine In machen und Versionen Ihrer CTE Take Out und dann UNION sie im Finale wie folgt wählen:

SELECT ... 
FROM cteSalesPerWeekDaysDINEIN 
UNION 
SELECT ... 
FROM cteSalesPerWeekDaysTAKEOUT 
+0

ist es möglich, mit den obigen zwei Abfragen zu zeigen? Bitte – Sachu