2012-02-16 11 views
7

Jeśli mam następującą tabelędezagregacji Tabela Ponad 2 Kolumny w T-SQL

Hour Clicks Conversions 
12:00 2 0 
1:00 3 2 
2:00 1 1 

Jak mogę napisać SELECT statment że dissaggrates go w obu kolumnach, więc otrzymujemy:

12:00 1 0 
12:00 1 0 
1:00 1 0 
1:00 1 1 
1:00 1 1 
2:00 1 1 

Jeśli nie mogę tego zrobić przy pomocy SELECT, w jaki sposób zapisać zapisany proces, który wykonuje to za pomocą pętli?

Dzięki!

+0

Tworzenie CLR SP –

+0

+1 ciekawy problem. Nie nowy, ale zajęło mi to kilka minut, aby wymyślić rozwiązanie, więc otrzymasz ode mnie ode mnie głosowanie. :-) –

+0

Nie widzę punktu drugiej kolumny, która wydaje się zawsze zwracać 1 –

Odpowiedz

5

Zakłada się, że będzie tylko jeden wiersz dla dowolnej wartości [Hour]. Jeśli mogą istnieć duplikaty, zbiorę je najpierw (zakładam, że źródło jest już agregacją jakiegoś rodzaju).

DECLARE @x TABLE ([Hour] CHAR(5), Clicks INT, Conversions INT); 

INSERT @x SELECT '12:00',2,0 
UNION ALL SELECT '13:00',3,2 
UNION ALL SELECT '14:00',1,1; 

;WITH x AS 
(
    SELECT n = ROW_NUMBER() OVER (ORDER BY s1.[object_id]) FROM sys.all_columns AS s1 
    -- CROSS JOIN (SELECT 1 UNION ALL SELECT 2) AS s2 -- to double the rows if you need more 
), 
y AS 
(
    SELECT [Hour], Conversions, Clicks, 
    m = MAX(CASE WHEN Conversions > Clicks THEN Conversions ELSE Clicks END) 
    FROM @x GROUP BY [Hour], Conversions, Clicks 
) 
SELECT y.[Hour], 
    Clicks = CASE WHEN Clicks < x.n THEN 0 ELSE 1 END, 
    Conversions = CASE WHEN Conversions < x.n THEN 0 ELSE 1 END 
FROM x INNER JOIN y ON x.n <= y.m 
ORDER BY CONVERT(TIME, y.[Hour]), Clicks, Conversions; 
2

To nie jest najbardziej efektywne podejście, ale może wystarczyć.

DECLARE @T TABLE (
    Hour   TIME 
    , Clicks  INT 
    , Conversions INT 
); 

INSERT @T VALUES ('12:00', 2, 0); 
INSERT @T VALUES ('1:00', 3, 2); 
INSERT @T VALUES ('2:00', 1, 1); 


DECLARE @Stage TABLE (
    Hour   TIME 
    , Clicks  INT 
    , Conversions INT 
); 

DECLARE @MaxClicks INT; 

SELECT @MaxClicks = MAX(Clicks) FROM @T; 

DECLARE @ClickCount INT; SET @ClickCount = 1; 

WHILE @ClickCount <= @MaxClicks 
BEGIN 
    INSERT @Stage (Hour, Clicks, Conversions) 
    SELECT Hour, 1, CASE WHEN Conversions >= @ClickCount THEN 1 ELSE 0 END 
    FROM @T WHERE Clicks >= @ClickCount; 

    SET @ClickCount = @ClickCount + 1; 
END; 

SELECT * FROM @Stage ORDER BY Hour; 
+0

Chociaż jest mało prawdopodobne (i wiem to tylko dlatego, że jestem zaznajomiony z typem modelu danych), co jeśli konwersje są wyższe niż kliknięcia dla danej godziny? na przykład Możliwe, że ktoś kliknął 3:59 i kupił o 4:01. –

+0

Punkt wzięty ... Mogłabym sobie wyobrazić, że twoje podejście do tabeli tabel będzie również bardziej efektywne. – JSR

+0

Myślę, że tak. Ale nazwij to tabelą liczb. To nic nie policzy. :-) –

0
DECLARE @x TABLE ([Hour] TIME, Clicks INT, Conversions INT); 
INSERT @x VALUES ('12:00',2,0),('13:00',3,2), ('14:00',1,1); 

;WITH a as 
(
SELECT [hour], 1 [unnessasary column], clicks, CASE WHEN clicks <= Conversions THEN 1 ELSE 0 END click, Conversions 
FROM @x 
UNION ALL 
SELECT [hour], 1, clicks-1,CASE WHEN clicks-1 <= Conversions THEN 1 ELSE 0 END, Conversions 
FROM a 
WHERE clicks > 1 
) 
SELECT [hour],[unnessasary column], click 
FROM a 
ORDER BY 1 
OPTION (maxrecursion 0) 
Powiązane problemy