SQL-запрос для несуществующих записей - PullRequest
0 голосов
/ 05 декабря 2018

Я унаследовал веб-сайт и соответствующую ему базу данных (SQL Server).Веб-сайт использует хранимые процедуры для извлечения данных из базы данных.Одна из этих хранимых процедур содержит сводку, и ее запуск занимает более 4 часов.В настоящее время это недопустимо.Я ищу помощь в замене сводной области стандартными запросами SQL, потому что я предполагаю, что это будет быстрее и обеспечит лучшую производительность.

Вот основной вопрос:

SELECT *
FROM (
    SELECT ac.AID
        ,ac.CatName AS t
        ,convert(INT, ac.Code) AS c
    FROM categories AS ac
    ) AS s
Pivot(Sum(c) FOR t IN (
            [tob]
            ,[ecit]
            ,[tobwcom]
            ,[rnorm]
            ,[raddict]
            ,[rpolicy]
            ,[ryouth]
            ,[rhealth]
            ,…
            )) AS p;

И результатысводной таблицы

|    AID    |    tob    |    ecit    |    tobwcom    |    rnorm    |
|-----------|-----------|------------|---------------|-------------|
|    1      |    1      |    NULL    |    NULL       |    0        |
|    2      |    1      |    NULL    |    NULL       |    1        |
|    3      |    1      |    NULL    |    NULL       |    0        |
|    4      |    1      |    NULL    |    NULL       |    0        |
|    5      |    1      |    NULL    |    NULL       |    0        |
|    6      |    1      |    NULL    |    NULL       |    1        |

Вот исходная таблица categories и некоторые примеры данных:

CREATE TABLE categories(
   ArticleID   INTEGER  NOT NULL  
  ,ThemeID     INTEGER  NOT NULL
  ,ThemeName   VARCHAR(7) NOT NULL
  ,Code        BIT  NOT NULL
  ,CreatedTime VARCHAR(7) NOT NULL
);
INSERT INTO categories(ArticleID,ThemeID,ThemeName,Code,CreatedTime) VALUES (1,1,'tob',1,'57:30.7');
INSERT INTO categories(ArticleID,ThemeID,ThemeName,Code,CreatedTime) VALUES (1,2,'ecig',1,'03:58.3');
INSERT INTO categories(ArticleID,ThemeID,ThemeName,Code,CreatedTime) VALUES (1,5,'rnorm',0,'42:56.5');
INSERT INTO categories(ArticleID,ThemeID,ThemeName,Code,CreatedTime) VALUES (2,1,'tob',1,'57:30.7');
INSERT INTO categories(ArticleID,ThemeID,ThemeName,Code,CreatedTime) VALUES (2,2,'ecig',0,'03:58.3');
INSERT INTO categories(ArticleID,ThemeID,ThemeName,Code,CreatedTime) VALUES (2,5,'rnorm',1,'42:56.5');
INSERT INTO categories(ArticleID,ThemeID,ThemeName,Code,CreatedTime) VALUES (2,6,'raddict',0,'42:59.8');
INSERT INTO categories(ArticleID,ThemeID,ThemeName,Code,CreatedTime) VALUES (3,1,'tob',1,'57:30.7');
INSERT INTO categories(ArticleID,ThemeID,ThemeName,Code,CreatedTime) VALUES (3,2,'ecig',0,'03:58.3');
INSERT INTO categories(ArticleID,ThemeID,ThemeName,Code,CreatedTime) VALUES (3,5,'rnorm',0,'42:56.5');
INSERT INTO categories(ArticleID,ThemeID,ThemeName,Code,CreatedTime) VALUES (21,1,'tob',1,'57:30.7');
INSERT INTO categories(ArticleID,ThemeID,ThemeName,Code,CreatedTime) VALUES (21,2,'ecig',0,'03:58.3');
INSERT INTO categories(ArticleID,ThemeID,ThemeName,Code,CreatedTime) VALUES (21,5,'rnorm',0,'42:56.5');
INSERT INTO categories(ArticleID,ThemeID,ThemeName,Code,CreatedTime) VALUES (21,6,'raddict',0,'42:59.8');

А вот таблица, содержащая имена категорий - (mytable на данный момент)

CREATE TABLE mytable(
   CatID       INTEGER  NOT NULL PRIMARY KEY 
  ,CatName     VARCHAR(7) NOT NULL
  ,CreatedTime DATETIME  NOT NULL
);
INSERT INTO mytable(CatID,CatName,CreatedTime) VALUES (1,'tob','2015-03-12 10:07:54.173');
INSERT INTO mytable(CatID,CatName,CreatedTime) VALUES (2,'ecig','2015-05-18 11:48:16.297');
INSERT INTO mytable(CatID,CatName,CreatedTime) VALUES (4,'tobwcom','2015-06-19 11:12:01.537');
INSERT INTO mytable(CatID,CatName,CreatedTime) VALUES (5,'rnorm','2015-06-22 14:24:02.317');
INSERT INTO mytable(CatID,CatName,CreatedTime) VALUES (6,'raddict','2015-06-22 14:24:13.957');
INSERT INTO mytable(CatID,CatName,CreatedTime) VALUES (7,'ecit','2015-06-22 14:26:18.437');

Что мне нужно, так это способ выполнения сводной способности по поиску несуществующих данных в categories.Вывод будет выглядеть примерно так:

|    AID    |    tob    |    ecit    |    tobwcom    |    rnorm    |
|-----------|-----------|------------|---------------|-------------|
|    1      |    1      |    NULL    |    NULL       |    0        |
|    2      |    1      |    NULL    |    NULL       |    1        |

Или список AID с и CatName с, которые не имеют никаких значений.Например:

| AID | CatName |
|-----|---------|
| 1   | ecit    |
| 1   | tobwcom |
| 2   | ecit    |
| 2   | tobwcom |

Я пытался

select distinct(AID) FROM [categories]
 where [CatName] not in ( 'ecit', 'tobwcom')

, но результаты этого, цифры, кажется, не складываются, однако это может быть ошибкой с моей стороны.

1 Ответ

0 голосов
/ 06 декабря 2018

Не уверен, что это будет достаточно быстро для такого огромного стола.Но для этого второго ожидаемого результата можно найти недостающее.

select a.ArticleID, c.CatName
from #myarticles a
cross join #mycategories c
left join categories ca on (ca.ArticleID = a.ArticleID and ca.ThemeID = c.CatID)
where ca.ArticleID is null;

Тест можно найти здесь

Обратите внимание, что этот метод выигрывает отобъединенный индекс первичного ключа включен (ArticleID, ThemeID)

В качестве альтернативы, LEFT JOIN с проверкой NULL может быть изменен на NOT EXISTS.

select a.ArticleID, c.CatName
from #myarticles a
join #mycategories c on c.CatID between 1 and 7
where NOT EXISTS
(
   select 1
   from categories ca 
   where ca.ArticleID = a.ArticleID 
     and ca.ThemeID = c.CatID
);
...