Reputation: 115
I have sql view like this:
id date_from date_to
1 2005-01-05 2005-05-10
1 2005-01-05 2005-05-10
1 2005-01-05 2005-05-10
2 2005-01-01 2006-08-31
2 2010-01-01 2010-06-30
3 2005-01-01 2005-06-30
And I want to write sql statement which returns:
1 2005-01-05 2005-05-10 2005-01-05 2005-05-10 2005-01-05 2005-05-10
2 2005-01-01 2006-08-31 2010-01-01 2010-06-30 NULL NULL
3 2005-01-01 2005-06-30 NULL NULL NULL NULL
Any ideas?
Upvotes: 1
Views: 2034
Reputation: 1781
Answers to Mark's question will help.
Which RDBMS is this - MySQL, Oracle, SQLServer...? Also, are you ever going to want more than three date_from, date_to pairs per id?
using t-sql, I explicitly handle 3 levels. If you want it to be dynamic, you need to create the query dynamically.
DECLARE @staging TABLE
(
id int NOT NULL,
date_from datetime NOT NULL,
date_to datetime NOT NULL,
step int
)
INSERT INTO @staging
SELECT id, date_from, date_to,
ROW_NUMBER() OVER(PARTITION BY id ORDER BY date_from, date_to)
FROM tblTemp
-- below is static for 3 levels, make below dynamic to match what you want
SELECT t1.id, t1.date_from, t1.date_to, t2.date_from, t2.date_to, t3.date_from, t3.date_to
FROM @staging t1 LEFT OUTER JOIN
@staging t2 ON t1.id = t2.id AND t2.step = 2 LEFT OUTER JOIN
@staging t3 ON t2.id = t3.id AND t3.step = 3
WHERE t1.step = 1
Test @ http://sqlfiddle.com/#!3/9daae/4/0
Upvotes: 1
Reputation: 62831
Because you're most recent questions have been related to MySQL, I'll assume you want a MySQL solution.
If you know the max number of potential date ranges, then you can use MAX and CASE. However, you have to have a row counter since you don't have any other unique identifier (I'd actually recommend adding that to your view since you mention this is a view). Here it is though:
SELECT Id,
MAX(CASE WHEN row_number = 1 THEN date_from END) date_from1,
MAX(CASE WHEN row_number = 1 THEN date_to END) date_to1,
MAX(CASE WHEN row_number = 2 THEN date_from END) date_from2,
MAX(CASE WHEN row_number = 2 THEN date_to END) date_to2,
MAX(CASE WHEN row_number = 3 THEN date_from END) date_from3,
MAX(CASE WHEN row_number = 3 THEN date_to END) date_to3
FROM (
SELECT
id,
@running:=if(@previous=id,@running,0) + 1 as row_number,
@previous:=id,
date_from, date_to
FROM YourView
JOIN (SELECT @previous := 0) r
ORDER BY id, date_from, date_to
) t
GROUP BY Id
If you don't know the maximum number of date ranges, then you won't be able to do this with a single SQL statement. Instead, you'll need to use dynamic SQL.
I'll assume you can add the row_number to your View and here is a close example:
SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(CASE WHEN row_number = ',
row_number,
' THEN date_from END) date_from',
row_number)
),
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(CASE WHEN row_number = ',
row_number,
' THEN date_to END) date_to',
row_number)
) INTO @sql
FROM YourView;
SET @sql = CONCAT('SELECT ID, ',
@sql, '
FROM YourView
GROUP BY ID');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Best of luck.
Upvotes: 1