簡體   English   中英

SQL Server查詢將表與另一個查詢的結果連接

[英]SQL Server query joining a table with the results of another query

我正在使用包含事件dbo.IncidentDimvw的數據表(第一個變量聲明中引用的dbo.IncidentDimvw

我正在嘗試生成一個查詢,該查詢將枚舉從最早的票證到今天的每個日期,以及每天“打開”和“關閉”的票證數量(可能為0)以及票證數量每天“ 打開 ”(不同於“打開”)。

為此,我需要一個與機票數據表無關的日期列表(即日歷)。 我能夠使用一些CTE來完成這項工作,從而在查詢中即時建立日期列表。

這部分工作正常,如果您希望看到它的運行,可以在下面測試我的代碼(為@SSOReportDateRangeBegin提供一個恆定值)。

我當前的查詢如下所示,並帶有描述性注釋。 它返回一個完整的日歷,從2012年12月27日到當前日期的每個日期都有一行(最多可擴展十年)。

我遇到的問題是,我不知道如何將dbo.IncidentDimvw加入該“日歷”,以獲取在每個日期打開,關閉和打開的票數。
CTE和DISTINCT選擇使我很難理解這些連接的結構方式。

我真正想要的是將日歷CTE的最終結果選擇為普通的舊數據集,從中可以比較票證-從而將日歷創建的邏輯與票證選擇的邏輯分開。

我已經嘗試過LEFT JOIN -ing dbo.IncidentDimvw到日歷查詢,但是當我選擇
COUNT(OpenedInc.ID) AS 'Incidents Opened'所產生的計數方式太大-這表明,我認為日歷邏輯與票選擇邏輯干擾-或許我不如何理解GROUP正確地在這種情況下。

/* Begin our date range with the earliest
   incident ticket creation date on record. (currently 12/27/2012)
   CAST is necessary because the CreatedDate column is a datetime value,
   and we specifically want to truncate the "time" portion
   for the purposes of this query.*/
DECLARE @SSOReportDateRangeBegin AS DATE =
    (SELECT MIN(CAST(inc.CreatedDate AS DATE)) FROM dbo.IncidentDimvw inc);

/* State how many years to include in our date range.
   Currently our range includes 10 years. (12/27/2012 - 12/26/2022)
   Later on, our selection will limit results to only dates <=CAST(GETDATE() AS DATE) */
DECLARE @SSOReportDateRangeYears AS INT = 10;
/* @SSOReportDateRangeYears cannot be greater than 31.
   For larger time periods, add CTEs for decades, centuries, millenia, etc. */

/* Calendar calculater based on a row counter with 31 rows.
   Calculates day 1 through day 31 for all 12 months, for 10 years.

   Since some months don't have 31 days, some DATEADD calculations
   will rollover to the next month, causing duplicate date values.
   (e.g. Feb 31st will be interpreted as Mar 3rd in non-leap year,
   Mar 2nd in leap-year, duplicating the date values for March 2nd or 3rd)

   SELECT DISTINCT is used to eliminate duplicate date values,
   giving us a clean and complete calendar to work with. */
WITH [counter](N) AS
(SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1),
SSOReportDays(N) AS (SELECT row_number() OVER (ORDER BY (SELECT NULL)) FROM [counter]),
SSOReportMonths(N) AS (SELECT N - 1 FROM SSOReportDays WHERE N <= 12),
SSOReportYears(N) AS (SELECT N - 1 FROM SSOReportDays WHERE N <= @SSOReportDateRangeYears)

SELECT DISTINCT

CAST(DATEADD(DAY, SSOReportDays.n,
     DATEADD(MONTH, SSOReportMonths.n,
     DATEADD(YEAR, SSOReportYears.n,
     DATEADD(DAY, -1, @SSOReportDateRangeBegin)))) AS DATE) AS CalendarDate
     /* Subtract 1 day from @SSOReportDateRangeBegin,
        because the counter will begin with the following day. */

/* CROSS JOIN to compute every possible combination
   of day(1-31) month(1-12) and year(1-10) */
FROM SSOReportYears CROSS JOIN SSOReportMonths CROSS JOIN SSOReportDays

/* Reduce calendar to <= the current date,
   since incident tickets cannot be created with future dates. */
WHERE CAST(DATEADD(DAY, SSOReportDays.n,
           DATEADD(MONTH, SSOReportMonths.n,
           DATEADD(YEAR, SSOReportYears.n,
           DATEADD(DAY, -1, @SSOReportDateRangeBegin)))) AS DATE) <= CAST(GETDATE() AS DATE)
           /* Subtract 1 day from @SSOReportDateRangeBegin,
              because the counter will begin with the following day. */

沒有什么可以阻止您向查詢中添加更多CTE。 您已經有4個CTE,為表中的日歷日期添加第五個CTE,為表中的工單計數添加第六個CTE,然后將工單計數與日歷CTE一起加入:

WITH [counter](N) AS
(SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1),
SSOReportDays(N) AS (SELECT row_number() OVER (ORDER BY (SELECT NULL)) FROM [counter]),
SSOReportMonths(N) AS (SELECT N - 1 FROM SSOReportDays WHERE N <= 12),
SSOReportYears(N) AS (SELECT N - 1 FROM SSOReportDays WHERE N <= @SSOReportDateRangeYears),
Calendar AS(
SELECT DISTINCT
CAST(DATEADD(DAY, SSOReportDays.n,
     DATEADD(MONTH, SSOReportMonths.n,
     DATEADD(YEAR, SSOReportYears.n,
     DATEADD(DAY, -1, @SSOReportDateRangeBegin)))) AS DATE) AS CalendarDate
     /* Subtract 1 day from @SSOReportDateRangeBegin,
        because the counter will begin with the following day. */

/* CROSS JOIN to compute every possible combination
   of day(1-31) month(1-12) and year(1-10) */
FROM SSOReportYears CROSS JOIN SSOReportMonths CROSS JOIN SSOReportDays

/* Reduce calendar to <= the current date,
   since incident tickets cannot be created with future dates. */
WHERE CAST(DATEADD(DAY, SSOReportDays.n,
           DATEADD(MONTH, SSOReportMonths.n,
           DATEADD(YEAR, SSOReportYears.n,
           DATEADD(DAY, -1, @SSOReportDateRangeBegin)))) AS DATE) <= CAST(GETDATE() AS DATE)),
TicketCount AS (
SELECT TicketDate, Status, Count(*) cnt -- These are just fake columns. Use your columns
FROM dbo.IncidentDimvw
GROUP BY TicketDate, Status)
SELECT c.CalendarDate, O.cnt, C.cnt, E.cnt
FROM Calendar c
LEFT JOIN TicketCount O ON c.CalendarDate = O.TicketDate AND O.Status = 'Open'
LEFT JOIN TicketCount C ON c.CalendarDate = C.TicketDate AND C.Status = 'Close'
LEFT JOIN TicketCount E ON c.CalendarDate = E.TicketDate AND E.Status = 'etc.' -- keep adding until you get all required statuses
ORDER BY 1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM