2016-01-07 4 views
2

Таблица: ПродуктSQL Server 2008 R2: Сводные показатели таблицы запроса

create table Product 
(
    productID int, 
    productName varchar(20), 
    productsalesdate DATETIME, 
    producttype varchar(20) 
); 

Вставка:

insert into product values(1,'PenDrive','2010-01-01','Electronic'); 
insert into product values(1,'Computer','2016-01-01','Electronic'); 
insert into product values(1,'Laptop','2011-02-02','Electronic'); 
insert into product values(2,'textbook','2014-02-02','books'); 
insert into product values(2,'notebook','2016-01-01','books'); 
insert into product values(3,'Car','2016-01-01','Vehicle'); 
insert into product values(3,'Bike','2016-01-07','Vehicle'); 

Сначала попробуйте: В этом я получаю неправильную сумму из ProductType

SELECT productID, FirstSale,LastSale, [Electronic],[books],[Vehicle] 
FROM 
(
    SELECT 
     productID, 
     MIN(ProductSalesdate) as FirstSale, 
     MAX(ProductSalesdate) as LastSale, 
     productType 
    FROM 
     Product 
    Group by productID,productType 
) a 
PIVOT 
(
    COUNT(productType) 
    FOR productType IN ([Electronic],[books],[Vehicle]) 
) AS pvt; 

Second Try: В этой попытке я решил проблему суммы, но запрос занимает больше времени для выполнения для огромных записей.

SELECT productID,FirstSale,LastSale ,[Electronic],[books],[Vehicle] 
FROM 
(
    SELECT a.ProductID, a.FirstSale, a.LastSale, b.ProductType 
    FROM Product b 
    inner join 
    (
     SELECT 
      productID, 
      MIN(ProductSalesdate) as FirstSale, 
      MAX(ProductSalesdate) as LastSale 
     FROM 
      Product 
     Group by productID 
    ) as a 
    ON a.ProductID = b.ProductID 
) ab 
PIVOT 
(
    COUNT(productType) 
    FOR productType IN ([Electronic],[books],[Vehicle]) 
) AS pvt; 

Примечание: Второй запрос работает нормально, но проблема с производительностью, из-за Я присоединяюсь два же таблицы, потому что, чтобы получить счетчик ProductType в запросе поворота.

Вопрос: Как оптимизировать второй запрос, который является моей второй попыткой?

+0

Могут ли продукты определенного 'productType' иметь одинаковые' productId'? –

+0

Кроме того, у вас есть производная таблица 'a' в вашей второй попытке, которая группируется в' productType, productId', но вы присоединяете ее к 'b' только на' productId' ... кажется fishy –

+0

Вы утверждаете, что у вас есть проблема с представление. Не могли бы вы описать это, пожалуйста? Требуются секунды, минуты, часы? Какое время исполнения вы ожидали? –

ответ

1

Следующая таблица использует временную таблицу для хранения производной таблицы ab. Я предполагаю, что это улучшит план выполнения второго запроса.

SELECT a.ProductID, a.FirstSale, a.LastSale, b.ProductType 
INTO #ab 
FROM Product b 
inner join 
(
    SELECT 
     productID, 
     MIN(ProductSalesdate) as FirstSale, 
     MAX(ProductSalesdate) as LastSale 
    FROM 
     Product 
    Group by productID 
) as a 
ON a.ProductID = b.ProductID; 

SELECT productID,FirstSale,LastSale ,[Electronic],[books],[Vehicle] 
FROM #ab AS ab 
PIVOT 
(
    COUNT(productType) 
    FOR productType IN ([Electronic],[books],[Vehicle]) 
) AS pvt; 

DROP TABLE #ab; 

EDIT: Только для занятий спортом я написал следующий скрипт, который имеет 15k строк в #product. Весь скрипт выполняется через ~ 1 секунду. Я до сих пор не понимаю, как ваш запрос занимает 5,5 минут. Здесь идет:

SET NOCOUNT ON; 

CREATE TABLE #product (
    product_id INT, 
    product_name VARCHAR(20), 
    product_sales_date DATE, 
    product_type VARCHAR(20) 
); 

DECLARE @cnt INT=0; 
WHILE @cnt<15000 
BEGIN 
    INSERT INTO #product(
     product_id, 
     product_name, 
     product_sales_date, 
     product_type 
    ) 
    SELECT 
     product_id=ROUND(20*RAND(),0), 
     product_name=LEFT(NEWID(),20), 
     product_sales_date=DATEADD(DAY,ROUND((-10+20*RAND()), 0),GETDATE()), 
     product_type= 
      CASE ROUND(2*RAND(),0) 
       WHEN 0 THEN 'Electronic' 
       WHEN 1 THEN 'books' 
       ELSE 'Vehicle' 
      END; 

    SET @[email protected]+1; 
END 

SELECT a.product_id, a.first_sale, a.last_sale, b.product_type 
INTO #ab 
FROM #product b 
inner join 
(
    SELECT 
     product_id, 
     MIN(product_sales_date) as first_sale, 
     MAX(product_sales_date) as last_sale 
    FROM 
     #product 
    GROUP BY 
     product_id 
) as a 
ON a.product_id= b.product_id; 

SELECT product_id,first_sale,last_sale,[Electronic],[books],[Vehicle] 
FROM #ab AS ab 
PIVOT 
(
    COUNT(product_type) 
    FOR product_type IN ([Electronic],[books],[Vehicle]) 
) AS pvt; 

DROP TABLE #ab; 
DROP TABLE #product; 
+0

Эй, спасибо, он делает что-то лучше. :) – MAK

+0

@MAK это приятно слышать =). Какое время исполнения? –

+0

Сейчас 5,5 мин. Это значимо для меня. – MAK

0

Кажется, что вы пытаетесь сделать что-то вроде этого .. Не знаю, почему вам нужно дополнительное присоединяется или временные таблицы ..

SELECT * FROM 
(
    SELECT productID, 
      productType, 
      MIN(ProductSalesdate) as FirstSale, 
      MAX(ProductSalesdate) as LastSale, 
      COUNT(productType) AS ProductCount 
    FROM Product 
    GROUP BY productID,productType 
) t 
PIVOT 
(
    SUM(ProductCount) 
    FOR productType IN ([Electronic],[books],[Vehicle]) 
) p 

вы получите NULLS для число 0, но вы можете легко совместить эти значения с 0

+0

У ОП были проблемы с производительностью с его запросом PIVOT, поэтому я предложил сначала материализовать производную таблицу на временную таблицу. Вполне возможно, что ваша версия улучшится. –

+0

@TT. от того, что я заметил в последнее время здесь, у pivot есть проблемы с производительностью, и лучше использовать эти уродливые агрегаты с аргументами case – JamieD77

+0

Очень верно. Я могу направить вас к этому [thread on SO] (http://stackoverflow.com/a/34770562/243373), в котором плохо работающий PIVOT был оптимизирован с использованием комбинации PIVOT старой школы (с использованием CASE) вместе с OPTION (HASH GROUP) для ускорения группировки. –

Смежные вопросы