SQL query: display different group value in different column - sql

I am trying to group by ticker, date and display their value in different columns for different tickers.
But I don't know the exact ticker name which are in my table.
original table(tickers may have other symbols besides A, B, C):
date | ticker | value
-------------------------
1 | A | 5
1 | B | 3
1 | C | 2
2 | A | 5
2 | B | 3
2 | C | 2
3 | A | 5
3 | B | 3
3 | C | 2
.......
Write the SQL query to get the result dataframe:
date | A | B | C
--------------------------------
1 | 5 | 3 | 2
2 | 5 | 3 | 2
3 | 5 | 3 | 2

As sgeddes states, this is accomplished with a pivot. You can create a pivot dynamically when you don't know all the values. I gave an example of doing just that here
https://dba.stackexchange.com/questions/98776/dynamic-select-and-place-result-in-variable-columns/98809#98809
create Table Questions
(
id int identity,
question_id int,
question_name varchar(255)
)
go
with CTEquestion
as
(
select 1 QID
union all
Select QID+1
from CTEquestion
where QID < 11
)
insert questions
select QID, 'Question'+cast(QID as varchar(50))
from CTEquestion
insert QuestionAnswers
values ('2015-04-23', 'a1', 1, 'Canswer1')
, ('2015-04-23', 'a1', 2, 'Ianswer2')
, ('2015-04-23', 'a1', 3, 'Canswer3')
, ('2015-04-23', 'a1', 4, 'Canswer4')
, ('2015-04-23', 'a1', 5, 'Ianswer5')
, ('2015-04-23', 'a1', 6, 'Ianswer6')
, ('2015-04-23', 'a1', 7, 'Canswer7')
, ('2015-04-23', 'a1', 8, 'Canswer8')
, ('2015-04-23', 'a1', 9, 'Canswer9')
, ('2015-04-23', 'a1', 10,'Canswer10')
insert QuestionAnswers
values (CONVERT(DATE, GETDATE()), 'b2', 1, 'Canswer1')
, (CONVERT(DATE, GETDATE()), 'b2', 2, 'Canswer2')
, (CONVERT(DATE, GETDATE()), 'b2', 3, 'Canswer3')
, (CONVERT(DATE, GETDATE()), 'b2', 4, 'Canswer4')
, (CONVERT(DATE, GETDATE()), 'b2', 5, 'Canswer5')
, (CONVERT(DATE, GETDATE()), 'b2', 6, 'Ianswer6')
, (CONVERT(DATE, GETDATE()), 'b2', 7, 'Canswer7')
, (CONVERT(DATE, GETDATE()), 'b2', 8, 'Canswer8')
, (CONVERT(DATE, GETDATE()), 'b2', 9, 'Canswer9')
, (CONVERT(DATE, GETDATE()), 'b2', 10, 'Ianswer10')
insert QuestionAnswers
values (CONVERT(DATE, GETDATE()), 'c3', 1, 'Ianswer1')
, (CONVERT(DATE, GETDATE()), 'c3', 2, 'Ianswer2')
, (CONVERT(DATE, GETDATE()), 'c3', 3, 'Canswer3')
, (CONVERT(DATE, GETDATE()), 'c3', 4, 'Ianswer4')
, (CONVERT(DATE, GETDATE()), 'c3', 5, 'Canswer5')
, (CONVERT(DATE, GETDATE()), 'c3', 6, 'Ianswer6')
, (CONVERT(DATE, GETDATE()), 'c3', 7, 'Canswer7')
, (CONVERT(DATE, GETDATE()), 'c3', 8, 'Canswer8')
, (CONVERT(DATE, GETDATE()), 'c3', 9, 'Canswer9')
, (CONVERT(DATE, GETDATE()), 'c3', 10, 'Ianswer10')
insert QuestionAnswers
values (CONVERT(DATE, GETDATE()), 'a1', 1, 'Canswer1')
, (CONVERT(DATE, GETDATE()), 'a1', 2, 'Ianswer2')
, (CONVERT(DATE, GETDATE()), 'a1', 3, 'Canswer3')
, (CONVERT(DATE, GETDATE()), 'a1', 4, 'Canswer4')
, (CONVERT(DATE, GETDATE()), 'a1', 5, 'Canswer5')
, (CONVERT(DATE, GETDATE()), 'a1', 6, 'Canswer6')
, (CONVERT(DATE, GETDATE()), 'a1', 7, 'Canswer7')
, (CONVERT(DATE, GETDATE()), 'a1', 8, 'Canswer8')
, (CONVERT(DATE, GETDATE()), 'a1', 9, 'Canswer9')
, (CONVERT(DATE, GETDATE()), 'a1', 10, 'Ianswer10')
-->End test data creation
--straight join
select qa.user_id, qa.question_set, q.question_id, qa.answer
from Questions q
join QuestionAnswers qa on qa.question_id=q.question_id
order by qa.user_id
--dynamic pivot
DECLARE
#questionList varchar(max)
, #maxQID int
, #qid int
select #questionList='',#maxQID = MAX(question_id), #qid= MIN(question_id)
FROM Questions
while #qid <= #maxQID
begin
set #questionList=#questionList+'['+cast(#qid as varchar(10))+']'
select #qid=min(question_id)
from Questions
where question_id > #qid
if #qid<=#maxQID
set #questionList=#questionList+', '
end
DECLARE #SQL NVARCHAR(MAX)
SET #SQL = N'
select user_id, '+#questionList+'
from
(select q.question_id, qa.question_set, qa.user_id, qa.answer
from Questions q
join QuestionAnswers qa on qa.question_id=q.question_id) x
PIVOT
(
max(answer)
FOR question_id in ('+#questionList+')
) pvt
order by user_id'
exec sp_executesql #SQL

If you know the ticker values you can do a GROUP BY. Use CASE to do conditional SUM:
select date,
SUM(case when ticker = 'A' then value end) as A,
SUM(case when ticker = 'B' then value end) as B,
SUM(case when ticker = 'C' then value end) as C,
...
from tablename
group by date
Core ANSI SQL-99.
If the different ticker values are unknown, and may change between executions, you need product specific functionality. (The general behavior is that a SELECT always return the same number of columns - independent of table data!)

Related

Identify rows subsequent to other rows based on criteria?

I am fairly new to DB2 and SQL. There exists a table of customers and their visits. I need to write a query to find visits by the same customer subsequent and within 24hr to a visit when Sale = 'Y'.
Based on this example data:
CustomerId
VisitID
Sale
DateTime
1
1
Y
2021-04-23 20:16:00.000000
2
2
N
2021-04-24 20:16:00.000000
1
3
N
2021-04-23 21:16:00.000000
2
4
Y
2021-04-25 20:16:00.000000
3
5
Y
2021-04-23 20:16:00.000000
2
6
N
2021-04-25 24:16:00.000000
3
7
N
2021-5-23 20:16:00.000000
The query results should return:
VisitID
3
6
How do I do this?
Try this. You may uncomment the commented out block to run this statement as is.
/*
WITH MYTAB (CustomerId, VisitID, Sale, DateTime) AS
(
VALUES
(1, 1, 'Y', '2021-04-23 20:16:00'::TIMESTAMP)
, (1, 3, 'N', '2021-04-23 21:16:00'::TIMESTAMP)
, (2, 2, 'N', '2021-04-24 20:16:00'::TIMESTAMP)
, (2, 4, 'Y', '2021-04-25 20:16:00'::TIMESTAMP)
, (2, 6, 'N', '2021-04-25 23:16:00'::TIMESTAMP)
, (3, 5, 'Y', '2021-04-23 20:16:00'::TIMESTAMP)
, (3, 7, 'N', '2021-05-23 20:16:00'::TIMESTAMP)
)
*/
SELECT VisitID
FROM MYTAB A
WHERE EXISTS
(
SELECT 1
FROM MYTAB B
WHERE B.CustomerID = A.CustomerID
AND B.Sale = 'Y'
AND B.VisitID <> A.VisitID
AND A.DateTime BETWEEN B.DateTime AND B.DateTime + 24 HOUR
)

SQL select max of a consecutive run of data

Given a table with a consecutive run of data: a number that always increases while a task is in progress and resets back to zero when the next task starts, how do you select the maximum of each run of data?
Each consecutive run can have any number of rows, and the runs of data are marked by a a "start" and "end" row, eg the data might look like
user_id, action, qty, datetime
1, start, 0, 2017-01-01 00:00:01
1, record, 0, 2017-01-01 00:00:01
1, record, 4, 2017-01-01 00:00:02
1, record, 5, 2017-01-01 00:00:03
1, record, 6, 2017-01-01 00:00:04
1, end, 0, 2017-01-01 00:00:04
1, start, 0, 2017-01-01 00:00:05
1, record, 0, 2017-01-01 00:00:05
1, record, 2, 2017-01-01 00:00:06
1, record, 3, 2017-01-01 00:00:07
1, end, 0, 2017-01-01 00:00:07
2, start, 0, 2017-01-01 00:00:08
2, record, 0, 2017-01-01 00:00:08
2, record, 3, 2017-01-01 00:00:09
2, record, 8, 2017-01-01 00:00:10
2, end, 0, 2017-01-01 00:00:10
And the results would be the maximum value of each run:
user_id, action, qty, datetime
1, record, 6, 2017-01-01 00:00:04
1, record, 3, 2017-01-01 00:00:07
2, record, 8, 2017-01-01 00:00:10
Using any postgres sql syntax (9.3)? Its some kind of grouping then selecting max from each group, but I don't see how to do the grouping part.
If theres no overlapping for a single user and the next run always starts at a later time, then you can use LAG() window function.
with the_table(user_id, action, qty, datetime) as (
select 1,'start', 0, '2017-01-01 00:00:01'::timestamp union all
select 1,'record', 0, '2017-01-01 00:00:01'::timestamp union all
select 1,'record', 4, '2017-01-01 00:00:02'::timestamp union all
select 1,'record', 5, '2017-01-01 00:00:03'::timestamp union all
select 1,'record', 6, '2017-01-01 00:00:04'::timestamp union all
select 1,'end', 0, '2017-01-01 00:00:04'::timestamp union all
select 1,'start', 0, '2017-01-01 00:00:05'::timestamp union all
select 1,'record', 0, '2017-01-01 00:00:05'::timestamp union all
select 1,'record', 2, '2017-01-01 00:00:06'::timestamp union all
select 1,'record', 3, '2017-01-01 00:00:07'::timestamp union all
select 1,'end', 0, '2017-01-01 00:00:07'::timestamp union all
select 2,'start', 0, '2017-01-01 00:00:08'::timestamp union all
select 2,'record', 0, '2017-01-01 00:00:08'::timestamp union all
select 2,'record', 3, '2017-01-01 00:00:09'::timestamp union all
select 2,'record', 8, '2017-01-01 00:00:10'::timestamp union all
select 2,'end', 0, '2017-01-01 00:00:10'::timestamp
)
select n_user_id, n_action, n_qty, n_datetime from (
select action,
lag(user_id) over(partition by user_id order by datetime, case when action = 'start' then 0 when action = 'record' then 1 else 2 end, qty) as n_user_id,
lag(action) over(partition by user_id order by datetime, case when action = 'start' then 0 when action = 'record' then 1 else 2 end, qty) as n_action,
lag(qty) over(partition by user_id order by datetime, case when action = 'start' then 0 when action = 'record' then 1 else 2 end, qty) as n_qty,
lag(datetime) over(partition by user_id order by datetime, case when action = 'start' then 0 when action = 'record' then 1 else 2 end, qty) as n_datetime
from the_table
)t
where action = 'end'
Because some action = record rows have same datetime as start and end rows, I use CASE in ORDER BY, to be clear that start is first, then is record and then end.
Quick and dirty, assuming runs do not overlap
with bounds as (select starts.rn, starts.datetime as s, ends.datetime as e from
(select datetime,ROW_NUMBER() OVER () as rn from runs where action = 'start' order by datetime) as starts
join
(select datetime,ROW_NUMBER() OVER () as rn from runs where action = 'end' order by datetime) as ends
on starts.rn = ends.rn)
,with_run as (SELECT *, (select rn from bounds where s <= r.datetime and e >= r.datetime) as run
from runs as r)
,max_qty as (
SELECT run,max(qty) as qty
from with_run
GROUP BY run)
SELECT s.user_id,s.action,s.qty,s.datetime from with_run as s join max_qty as f on s.run = f.run AND s.qty = f.qty;
-- TEST DATA --
create table runs (user_id int, action text, qty int, datetime TIMESTAMP);
insert INTO runs VALUES
(1, 'start', 0, '2017-01-01 00:00:01')
,(1, 'record', 0, '2017-01-01 00:00:01')
,(1, 'record', 4, '2017-01-01 00:00:02')
,(1, 'record', 5, '2017-01-01 00:00:03')
,(1, 'record', 6, '2017-01-01 00:00:04')
,(1, 'end', 0, '2017-01-01 00:00:04')
,(1, 'start', 0, '2017-01-01 00:00:05')
,(1, 'record', 0, '2017-01-01 00:00:05')
,(1, 'record', 2, '2017-01-01 00:00:06')
,(1, 'record', 3, '2017-01-01 00:00:07')
,(1, 'end', 0, '2017-01-01 00:00:07')
,(2, 'start', 0, '2017-01-01 00:00:08')
,(2, 'record', 0, '2017-01-01 00:00:08')
,(2, 'record', 3, '2017-01-01 00:00:09')
,(2, 'record', 8, '2017-01-01 00:00:10')
,(2, 'end', 0, '2017-01-01 00:00:10');
UPDATE
#Oto Shavadze answer can be shortened
with lookup as (select action,lag(t.*) over(order by datetime, case when action = 'start' then 0 when action = 'record' then 1 else 2 end) as r from runs t)
select (r::runs).user_id
,(r::runs).action
,(r::runs).qty
,(r::runs).datetime
from lookup where action = 'end';
I think OP unclear about what considers maximum, last record before end or highest qty in run.

SQL - Start and End date based on another column

Simplified structure.
I need the two dates between a record that has an action type of 4 and an action type of 1.
The record could be in that state multiple times and I would need separate rows for their times
For example for IncidentId = 1
Row 1 - StartTime = 2017-01-01 14:00 (id:3) - End Time = 2017-01-01 20:00 (id: 5)
Row 2 - StartTime = 2017-01-01 21:00 (id:6) - End Time = 2017-01-02 11:00 (id: 9)
CREATE TABLE #returntable
(
[incidentid] INT,
[starttime] DATETIME,
[endtime] DATETIME
)
CREATE TABLE #testtableofdoom
(
[incidentlogid] INT,
[incidentid] INT,
[timestamp] DATETIME,
[actiontypeid] INT
)
INSERT INTO #testtableofdoom
( incidentlogid, incidentid, timestamp, actiontypeid )
VALUES ( 1, 1, '2017-01-01 09:00', 1 )
, ( 2, 1, '2017-01-01 11:00', 1 )
, ( 3, 1, '2017-01-01 14:00', 4 )
, ( 4, 1, '2017-01-01 16:00', 4 )
, ( 5, 1, '2017-01-01 20:00', 1 )
, ( 6, 1, '2017-01-01 21:00', 4 )
, ( 7, 1, '2017-01-02 09:00', 4 )
, ( 8, 2, '2017-01-02 10:00', 1 )
, ( 9, 1, '2017-01-02 11:00', 1 )
, ( 10, 1, '2017-01-02 14:00', 1 )
, ( 11, 2, '2017-01-02 15:00', 4 )
, ( 12, 1, '2017-01-02 16:00', 1 )
, ( 13, 1, '2017-01-02 17:00', 1 )
, ( 14, 1, '2017-01-02 18:00', 1 )
, ( 15, 2, '2017-01-02 15:00', 1 );
DROP TABLE #testtableofdoom
DROP TABLE #returntable
I used table variables instead of temp tables, and shorter column names than you, but this works:
declare #tt TABLE (
logId INT, iId INT,
dt DATETIME, atId INT
INSERT #tt (logId, iId,
dt, atId) values
(1, 1, '2017-01-01 09:00', 1),
(2, 1, '2017-01-01 11:00', 1),
(3, 1, '2017-01-01 14:00', 4),
(4, 1, '2017-01-01 16:00', 4),
(5, 1, '2017-01-01 20:00', 1),
(6, 1, '2017-01-01 21:00', 4),
(7, 1, '2017-01-02 09:00', 4),
(8, 2, '2017-01-02 10:00', 1),
(9, 1, '2017-01-02 11:00', 1),
(10, 1, '2017-01-02 14:00', 1),
(11, 2, '2017-01-02 15:00', 4),
(12, 1, '2017-01-02 16:00', 1),
(13, 1, '2017-01-02 17:00', 1),
(14, 1, '2017-01-02 18:00', 1),
(15, 2, '2017-01-02 15:00', 1)
Select s.logId startLogid, e.logId endLogId,
s.iID, s.dt startTime, e.dt endTime
from #tt s join #tt e
on e.logId =
(Select min(logId) from #tt
where iId = s.iID
and atId = 1
and logId > s.logId)
where s.aTid = 4
and ((Select atId from #tt
Where logId =
(Select Max(logId) from #tt
where logId < s.LogId
and iId = s.iId)) = 1
or Not Exists
(Select * from #tt
Where logId < s.LogId
and iId = s.iID))
This produces the following:
startLogid endLogId iID startTime endTime
----------- ----------- ---- ---------------- ----------------
3 5 1 2017-01-01 14:00 2017-01-01 20:00
6 9 1 2017-01-01 21:00 2017-01-02 11:00
11 15 2 2017-01-02 15:00 2017-01-02 15:00
it uses a self-join. s represents the first (start) record with actionType 4, and e represents end record with action type 1. Since logId increments, the end record must have higher logId than the start record, and it must be the lowest logId higher than the start records that has same iId and an atId = 1.
Select s.iID, s.dt startTime, e.dt endTime
from #tt s join #tt e
on e.logId =
(Select min(logId) from #tt -- lowest log greater than start logId
where iId = s.iID -- same iId
and atId = 1 -- with atId = 1
and logId > s.logId) -- greater than start logId
finally, the start record must be restricted to those "4" records which either have no other same incident records before it or have a "1" record immediately prior to it.
where s.aTid = 4
and ((Select atId from #tt -- atId of immed prior = 1
Where logId =
(Select Max(logId) from #tt
where logId < s.LogId
and iId = s.iId)) = 1
or Not Exists -- or there is no prior record
(Select * from #tt
Where logId < s.LogId
and iId = s.iID))
something like this?
select
d.[timestamp] as StartDate,
(select top 1 [timestamp]
from #testTableOfDoom d2
where d2.incidentid = 1 and d2.[timestamp] > d.[timestamp] and actiontypeid = 1
order by d2.[timestamp] asc
) as EndDate
from
(select
p.[timestamp],
LAG(p.actiontypeid) OVER (ORDER BY incidentlogid asc) PrevValue,
p.actiontypeid
from #testTableOfDoom p
where p.incidentid = 1) d
where d.actiontypeid = 4
and d.PrevValue <> 4

SQL Server - Selecting periods without changes in data

What I am trying to do is to select periods of time where the rest of data in the table was stable based on one column and check was there a change in second column value in this period.
Table:
create table #stable_periods
(
[Date] date,
[Car_Reg] nvarchar(10),
[Internal_Damages] int,
[External_Damages] int
)
insert into #stable_periods
values ('2015-08-19', 'ABC123', 10, 10),
('2015-08-18', 'ABC123', 9, 10),
('2015-08-17', 'ABC123', 8, 9),
('2015-08-16', 'ABC123', 9, 9),
('2015-08-15', 'ABC123', 10, 10),
('2015-08-14', 'ABC123', 10, 10),
('2015-08-19', 'ABC456', 5, 3),
('2015-08-18', 'ABC456', 5, 4),
('2015-08-17', 'ABC456', 8, 4),
('2015-08-16', 'ABC456', 9, 4),
('2015-08-15', 'ABC456', 10, 10),
('2015-01-01', 'ABC123', 1, 1),
('2015-01-01', 'ABC456', NULL, NULL);
--select * from #stable_periods
-- Unfortunately I can’t post pictures yet but you get the point of how the table looks like
What I would like to receive is
Car_Reg FromDate ToDate External_Damages Have internal damages changed in this period?
ABC123 2015-08-18 2015-08-19 10 Yes
ABC123 2015-08-16 2015-08-17 9 Yes
ABC123 2015-08-14 2015-08-15 10 No
ABC123 2015-01-01 2015-01-01 1 No
ABC456 2015-08-19 2015-08-19 3 No
ABC456 2015-08-16 2015-08-18 4 Yes
ABC456 2015-08-15 2015-08-15 10 No
ABC456 2015-01-01 2015-01-01 NULL NULL
Basically to build period frames where [External_Damages] were constant and check did the [Internal_Damages] change in the same period (doesn't matter how many times).
I spend a lot of time trying but I am afraid that my level of abstraction thinking in much to low...
Will be great to see any suggestions.
Thanks,
Bartosz
I believe this is a form of Islands Problem.
Here is a solution using ROW_NUMBER and GROUP BY:
SQL Fiddle
WITH CTE AS(
SELECT *,
RN = DATEADD(DAY, - ROW_NUMBER() OVER(PARTITION BY Car_reg, External_Damages ORDER BY [Date]), [Date])
FROM #stable_periods
)
SELECT
Car_Reg,
FromDate = MIN([Date]),
ToDate = MAX([Date]) ,
External_Damages,
Change =
CASE
WHEN MAX(External_Damages) IS NULL THEN NULL
WHEN COUNT(DISTINCT Internal_Damages) > 1 THEN 'Yes'
ELSE 'No'
END
FROM CTE c
GROUP BY Car_Reg, External_Damages, RN
ORDER BY Car_Reg, ToDate DESC

(Not) complicated sql query !

LookupTable:
userid, mobileid, startedate, enddate , owner
1 , 1 , 12-12-2000, 01-01-2001, asd
2 , 2 , 12-12-2000, 01-01-2001, dgs
3 , 3 , 02-01-2001, 01-01-2002, sdg
4 , 4 , 12-12-2000, 01-01-2001, sdg
UserInfoTable:
userid, firstname, lastname, address
1 , tom , do , test
2 , sam , smith , asds
3 , john , saw , asdasda
4 , peter , winston , near by
Mobile:
Mobileid, Name , number, imeinumber
1 , apple , 123 , 1111111
2 , nokia , 456 , 2222222
3 , vodafone , 789 , 3333333
CallLogs:
id , Mobileid, callednumbers (string), date , totalduration
1 , 1 , 123,123,321 , 13-12-2000 , 30
2 , 1 , 123,123,321 , 14-12-2000 , 30
3 , 2 , 123,123,321 , 13-12-2000 , 30
4 , 2 , 123,123,321 , 14-12-2000 , 30
5 , 3 , 123,123,321 , 13-12-2000 , 30
6 , 3 , 123,123,321 , 14-12-2000 , 30
7 , 1 , 123,123,321 , 13-01-2002 , 30
8 , 1 , 123,123,321 , 14-01-2002 , 30
I want a query which will return me the following:
firstname, lastname, mobile.name as mobilename, callednumbers (as concatinated strings from different rows in CallLogs table) and need it for year 2000
example:
firstname, lastname, mobilename, callednumbers
tom , do , apple , 123,123,321, 123,123,321
sam , smith , nokia , 123,123,321, 123,123,321
peter , winston , apple , 123,123,321, 123,123,321
any help will be highly appreciated...
I have tried this but no sucess.. tom is getting sams calls and vice versa. I am using sql server.
SELECT DISTINCT firstname,
lastname,
mobilename,
callednumbers
FROM ([testdatabase].[dbo].[LookupTable] lt
INNER JOIN [testdatabase].[dbo].[UserInfoTable] user1
ON lt.userid = user1.id)
INNER JOIN [testdatabase].[dbo].[Mobile] device1
ON lt.mobileid = device1.id
INNER JOIN [testdatabase].[dbo].[CallLogs] log1
ON lt.mobileid = log1.deviceid
WHERE lt.starttime LIKE '%2000%'
ORDER BY firstname
DECLARE #LookupTable TABLE (
userid INT,
mobileid INT,
startedate DATETIME,
enddate DATETIME,
owner CHAR(3))
INSERT INTO #LookupTable
SELECT 1, 1, '20001212 00:00:00.000', '20010101 00:00:00.000', N'asd' UNION ALL
SELECT 2, 2, '20001212 00:00:00.000', '20010101 00:00:00.000', N'dgs' UNION ALL
SELECT 3, 3, '20010102 00:00:00.000', '20020101 00:00:00.000', N'sdg' UNION ALL
SELECT 4, 4, '20001212 00:00:00.000', '20010101 00:00:00.000', N'sdg'
DECLARE #UserInfoTable TABLE (
userid INT,
firstname VARCHAR(10),
lastname VARCHAR(10),
address VARCHAR(10))
INSERT INTO #UserInfoTable
SELECT 1, N'tom', N'do', N'test' UNION ALL
SELECT 2, N'sam', N'smith', N'asds' UNION ALL
SELECT 3, N'john', N'saw', N'asdasda' UNION ALL
SELECT 4, N'peter', N'winston', N'near by'
DECLARE #Mobile TABLE (
mobileid INT,
name VARCHAR(10),
number INT,
imeinumber INT )
INSERT INTO #Mobile
SELECT 1, N'apple', 123, 1111111 UNION ALL
SELECT 2, N'nokia', 456, 2222222 UNION ALL
SELECT 3, N'vodafone', 789, 3333333
DECLARE #CallLogs TABLE (
id INT,
mobileid INT,
callednumbers VARCHAR(50),
[date] DATETIME,
totalduration INT )
INSERT INTO #CallLogs
SELECT 1, 1, N'123,123,321', '20001213 00:00:00.000', 30 UNION ALL
SELECT 2, 1, N'123,123,321', '20001214 00:00:00.000', 30 UNION ALL
SELECT 3, 2, N'123,123,321', '20001213 00:00:00.000', 30 UNION ALL
SELECT 4, 2, N'123,123,321', '20001214 00:00:00.000', 30 UNION ALL
SELECT 5, 3, N'123,123,321', '20001213 00:00:00.000', 30 UNION ALL
SELECT 6, 3, N'123,123,321', '20001214 00:00:00.000', 30 UNION ALL
SELECT 7, 1, N'123,123,321', '20020113 00:00:00.000', 30 UNION ALL
SELECT 8, 1, N'123,123,321', '20020114 00:00:00.000', 30
SELECT DISTINCT firstname,
lastname,
device1.name AS mobilename,
stuff((select ',' + callednumbers
from #CallLogs log1
where lt.mobileid = log1.mobileid
for xml path('')), 1, 1, '') AS callednumbers
FROM (#LookupTable lt
INNER JOIN #UserInfoTable user1
ON lt.userid = user1.userid)
INNER JOIN #Mobile device1
ON lt.mobileid = device1.mobileid
WHERE lt.startedate > '20000101' AND startedate < '20010101'
ORDER BY firstname