0

我不得不重新编写一个使用 SQL 查询和 ColdFusion 中的查询组合完成的项目。有几十个查询引用了原始 SQL 查询结果集,但它没有被抽象为适用于不同的事件。所以我想通过将大部分计数转移到 SQL 中来改进它。我得到了他们需要工作的前 6 个计数(不确定是否以最佳方式)。但是,除此之外,我不仅需要对整个日期范围进行细分,而且还需要对该日期范围内的每一天进行细分,以获取唯一计数。

到目前为止,查询是:

 SELECT Count(CASE
           WHEN type IN ( 1, 3, 4, 5, 9 ) THEN barcode
           ELSE NULL
         END)              AS total_scans,
   Count(CASE
           WHEN type IN ( 2, 8 ) THEN barcode
           ELSE NULL
         END)              AS total_creds,
   Count(barcode)          AS total_scans,
   Count(DISTINCT CASE
                    WHEN type IN ( 1, 3, 4, 5, 9 ) THEN barcode
                    ELSE NULL
                  END)     AS unique_scans,
   Count(DISTINCT CASE
                    WHEN type IN ( 2, 8 ) THEN barcode
                    ELSE NULL
                  END)     AS unique_creds,
   Count(DISTINCT barcode) AS unique_scans 
FROM   (SELECT c.id,
           a.barcode,
           d.type,
           c.location,
           Datepart(mm, a.scan_time)     AS scan_month,
           Datepart(dd, a.scan_time)     AS scan_day,
           Datepart(hour, a.scan_time)   AS scan_hour,
           Datepart(minute, a.scan_time) AS scan_min
    FROM   [scan_11pc_gate_entries] AS a
           INNER JOIN scan_units AS b
                   ON a.scanner = b.id
           INNER JOIN scan_gates AS c
                   ON b.gate = c.id
           INNER JOIN [scan_11pc_gate_allbarcodes] AS d
                   ON a.barcode = d.barcode
    WHERE  ( c.id IN (SELECT id
                      FROM   scan_gates
                      WHERE  ( event_id = 21 )) )
           AND ( a.valid IN ( 1, 8 ) )
           AND a.scan_time >= '20110808'
           AND a.scan_time <= '20110814') data  
4

1 回答 1

0

好吧,我在这里看到了很多其他改进/优化的空间,但要满足眼前的要求:

 SELECT d, Count(CASE WHEN type IN ( 1, 3, 4, 5, 9 ) THEN barcode
           ELSE NULL END) AS total_scans,
   Count(CASE WHEN type IN ( 2, 8 ) THEN barcode
           ELSE NULL END) AS total_creds,
   Count(barcode)         AS total_scans,
   Count(DISTINCT CASE WHEN type IN ( 1, 3, 4, 5, 9 ) THEN barcode
           ELSE NULL END) AS unique_scans,
   Count(DISTINCT CASE WHEN type IN ( 2, 8 ) THEN barcode
           ELSE NULL END) AS unique_creds,
   Count(DISTINCT barcode) AS unique_scans 
FROM   (SELECT c.id, -- is this column necessary?
           a.barcode,
           d.type,
           c.location, -- is this column necessary?
           d = DATEADD(DAY, DATEDIFF(DAY, 0, a.scan_time), 0)
    FROM   [scan_11pc_gate_entries] AS a
           INNER JOIN scan_units AS b
                   ON a.scanner = b.id
           INNER JOIN scan_gates AS c
                   ON b.gate = c.id
                  AND c.event_id = 21 -- join criteria, 
                     -- shouldn't be an extra IN clause
           INNER JOIN [scan_11pc_gate_allbarcodes] AS d
                   ON a.barcode = d.barcode
    WHERE  ( a.valid IN ( 1, 8 ) )
           AND a.scan_time >= '20110808'
           AND a.scan_time <= '20110814') data  
GROUP BY d
ORDER BY d;

请注意,>=and 与<=, 相同BETWEEN,除非scan_timeDATE列(或保证始终在午夜),否则您使用的方法并不安全。最好说:

           AND a.scan_time >= '20110808'
           AND a.scan_time <  '20110815'

更多信息在这里:


编辑

了解这是基于我从评论和问题中拼凑的信息,这与您的环境和工作负载的完整情况相去甚远,您可能会发现有用的索引视图是:

CREATE VIEW dbo.myview 
WITH SCHEMABINDING
AS
  SELECT c.event_id,
         a.barcode,
         [type] = CASE WHEN d.[type] IN (2,8) THEN 'c' ELSE 's' END,
         scan_date = DATEADD(DAY, DATEDIFF(DAY, 0, a.scan_time), 0),
         total = COUNT_BIG(*)
    FROM dbo.scan_11pc_gate_entries AS a
    INNER JOIN dbo.can_units AS b
            ON a.scanner = b.id
    INNER JOIN dbo.scan_gates AS c
            ON b.gate = c.id
    INNER JOIN dbo.scan_11pc_gate_allbarcodes AS d
            ON a.barcode = d.barcode
    WHERE (a.valid IN (1,8))
      AND d.[type] IN (2,3,4,5,8,9)
    GROUP BY 
      c.event_id,
      a.barcode,
      CASE WHEN d.[type] IN (2,8) THEN 'c' ELSE 's' END,
      DATEADD(DAY, DATEDIFF(DAY, 0, a.scan_time), 0);
GO
CREATE UNIQUE CLUSTERED INDEX x 
  ON dbo.myview(event_id, barcode, [type], scan_date);

现在您可以编写一个执行以下操作的查询:

SELECT [date] = CONVERT(CHAR(8), scan_date, 112), 
  SUM(CASE WHEN [type] = 's' THEN total ELSE 0 END) AS total_scans,
  SUM(CASE WHEN [type] = 'c' THEN total ELSE 0 END) AS total_creds,
  COUNT(CASE WHEN [type] = 's' THEN 1 END) AS unique_scans,
  COUNT(CASE WHEN [type] = 'c' THEN 1 END) AS unique_creds
FROM dbo.myview WITH (NOEXPAND) -- in case STD Edition
WHERE event_id = 21
  AND scan_date BETWEEN '20110808' AND '20110814'
GROUP BY scan_date
UNION ALL
SELECT [date] = 'weekly', 
  SUM(CASE WHEN [type] = 's' THEN total ELSE 0 END) AS total_scans,
  SUM(CASE WHEN [type] = 'c' THEN total ELSE 0 END) AS total_creds,
  COUNT(DISTINCT CASE WHEN [type] = 's' THEN barcode END) AS unique_scans,
  COUNT(DISTINCT CASE WHEN [type] = 'c' THEN barcode END) AS unique_creds
FROM dbo.myview WITH (NOEXPAND) -- in case STD Edition
WHERE event_id = 21
  AND scan_date BETWEEN '20110808' AND '20110814'
ORDER BY [date];

这一切都完全未经测试,因为您的架构尝试创建系统的完整复制品有点麻烦,但希望这能给您一个大致的工作思路......

于 2013-03-29T19:43:43.787 回答