Related
I have a table:
Project_Id Period Value
123 Jan-15 0
123 Feb-15 34
123 Mar-15 78
123 Apr-15 56
456 Jan-15 0
456 Feb-15 0
456 Mar-15 0
456 Apr-15 0
789 Jan-15 45
789 Feb-15 4
789 Mar-15 18
789 Apr-15 26
I need to retrieve Project data only when i do not have 0 for Value field in all the months like:
Project_Id Period Value
123 Jan-15 0
123 Feb-15 34
123 Mar-15 78
123 Apr-15 56
789 Jan-15 45
789 Feb-15 4
789 Mar-15 18
789 Apr-15 26
Project no 456 should not come in my result because for all the months the value is 0 for that particular project.
Can someone help me with the query?
Use SUM and COUNT to determine the number of 0 Values:
SELECT *
FROM tbl
WHERE project_id IN(
SELECT project_id
FROM tbl
GROUP BY project_id
HAVING SUM(CASE WHEN Value = 0 THEN 1 ELSE 0 END) <> COUNT(*)
)
SQL Fiddle
Another solution is to use EXISTS:
SELECT *
FROM tbl t1
WHERE EXISTS(
SELECT 1 FROM tbl t2 WHERE t2.project_id = t1.project_id AND t2.Value > 0
)
SQL Fiddle
The inner select gets all project_ids that have a least one value that is not 0.
select * from your_table
where project_id in
(
select project_id
from your_table
group by project_id
having sum(case when value <> 0 then 1 else 0 end) > 0
)
Some test data but idea remains the same
create table #test123
(
pid int,
value int
)
insert into #test123
select 1,0
union all
select 1,1
union all
select 2,0
union all
select 2,0
union all
select 3,2
select * from #test123 t2 where exists (select 1 from #test123 t1
where t1.pid=t2.pid
group by pid
having sum(value)>0
)
For performance, I prefer not making a join to check for repeating values:
;WITH CTE as
(
SELECT
Project_Id,
Period,
Value,
max(abs(value)) over (Partition by Period) value
FROM YourTable
)
SELECT
Project_Id,
Period,
Value
FROM CTE
WHERE value > 0
*using abs to check for negative values. If all values are positive, the abs can be omitted.
I have a SQL Server query that I want to do a left join to 2 tables. I need it to return all of the rows in the 1st table and only the matching data in the other 2 tables. My first incarnation created some sort of cross product with more than 10 times the required rows. So I added a rowcount function and had it filter for all rowcount values = 1. Now it returns the correct number of rows but with the wrong data from the other 2 tables.
I have certain filter rules (case statements) I apply to the contents of the 2 right tables to determine what, if anything, to return. I think this may be the source of the problem, but I'm not sure. I've tried using the filter code both within the select statement and as a where statement at the end of the query and even as part of the join on statement. I also tried using cross and outer applies. All to no avail.
I'm trying to achieve this without using loops. Is it possible? Please see the code below. This code generates too many rows. I won't repeat the 2nd iteration as it adds an extra select on top and a filter for m= 1 to the bottom to generate the correct number of rows.
These are the 2 tables that I am left joining to. Note that the 2nd table is only a small subset of a much larger table.
Thanks!!!
SELECT
GLENTRY.Fac + GLENTRY.Rundt + GLENTRY.Jrnllog AS UniqueID,
GLENTRY.Fac AS Fac,
(CASE WHEN
EntityTranslate2014.AcctEnd <> '' AND EntityTranslate2014.AcctEnd = SUBSTRING(GLENTRY.Acct,6,3)
THEN
EntityTranslate2014.Entity
ELSE
CASE WHEN
EntityTranslate2014.AcctEnd <> 0 AND EntityTranslate2014.Acct = GLENTRY.Acct
THEN
EntityTranslate2014.Entity
ELSE
CASE WHEN
EntityTranslate2014.SSDept <> 0 AND EntityTranslate2014.SSDept = SUBSTRING(GLENTRY.Acct,1,4)
THEN
EntityTranslate2014.Entity
ELSE
CASE WHEN
EntityTranslate2014.SSDept = 0
AND
EntityTranslate2014.AcctEnd = ''
AND
EntityTranslate2014.Acct = 0
THEN
EntityTranslate2014.Entity
ELSE
''
END
END
END
END)
AS NEWEntity,
(CASE WHEN AcctTranslate2014.Fac = GLENTRY.Fac OR AcctTranslate2014.Fac = '0'
THEN
AcctTranslate2014.NEWDept
ELSE
Null
END)
AS Department,
(CONVERT(DATETIME,GLENTRY.Period + '/01/' +
CASE WHEN
CONVERT(NVARCHAR(4),GLENTRY.Yearz) = ''
THEN
'2014'
ELSE
GLENTRY.Yearz
END)
AS YEARPER,
GLENTRY.Acct) AS SSAcct,
CONVERT(NVARCHAR(20),
CASE WHEN
AcctTranslate2014.Fac = GLENTRY.Fac OR AcctTranslate2014.Fac = '0'
THEN
AcctTranslate2014.NEWAcct
ELSE
Null
END)
AS NEWAccount,
GLENTRY.Rundt,
GLENTRY.Jrnlid,
GLENTRY.Amount,
GLENTRY.Dc,
GLENTRY.Ref,
GLENTRY.Refdt,
CONVERT(NVARCHAR(100),'Import of SS ' + CONVERT(VARCHAR(2),GLENTRY.Period) + '/' + CONVERT(VARCHAR(4),GLENTRY.Yearz) + ' GL activity') AS Descr,
GLENTRY.Invnr,
GLENTRY.Jrnllog,
ROW_NUMBER() OVER(PARTITION BY GLENTRY.Fac, GLENTRY.Yearz, GLENTRY.Period, GLENTRY.Pagez, GLENTRY.Acct, GLENTRY.Rundt, GLENTRY.Jrnlid,
GLENTRY.Amount, GLENTRY.Dc, GLENTRY.Ref, GLENTRY.Refdt, GLENTRY.Descr, GLENTRY.Invnr, GLENTRY.Origfac, GLENTRY.Jrnllog, GLENTRY.Seq
ORDER BY GLENTRY.Fac, GLENTRY.Yearz, GLENTRY.Period) AS m
FROM GLENTRY
LEFT OUTER JOIN
EntityTranslate2014 ON GLENTRY.Fac = EntityTranslate2014.Fac
LEFT OUTER JOIN
AcctTranslate2014 ON CONVERT(VARCHAR(8),GLENTRY.Acct) = AcctTranslate2014.SSAcct
WHERE GLENTRY.Yearz = 2014 AND GLENTRY.Period = 11
EntityTranslate2014 File
Fac Entity Descr AcctEnd SSDept Acct
1 51900 Entity1 0 0
2 50901 Entity2 0 0
3 10100 Entity3 0 0
3 10500 Entity4 4016 0
3 10500 Entity4 4020 0
3 10500 Entity4 4022 0
3 10500 Entity4 4024 0
3 10500 Entity4 4028 0
3 10500 Entity4 7016 0
4 30900 Entity5 0 0
5 10300 Entity6 0 0
6 11300 Entity7 0 0
7 11100 Entity8 0 0
7 11500 Entity9 4016 0
7 11500 Entity9 4020 0
7 11500 Entity9 4022 0
7 11500 Entity9 4024 0
7 11500 Entity9 4028 0
7 11500 Entity9 7016 0
9 32909 Entity10 0 0
10 12100 Entity11 0 0
11 32901 Entity12 0 0
12 53900 Entity13 0 0
13 10200 Entity14 0 0
14 32914 Entity15 0 0
15 32915 Entity16 0 0
16 11200 Entity17 0 0
17 32917 Entity18 0 0
18 32918 Entity19 0 0
19 32919 Entity20 0 0
20 32920 Entity21 0 0
21 13100 Entity22 0 0
22 52900 Entity23 0 0
89 99900 Entity24 0 0
123 12300 Entity25 0 0
124 12200 Entity26 0 0
133 13300 Entity27 0 0
201 11201 Entity28 0 0
202 11202 Entity29 0 0
402 25402 Entity30 0 0
403 25403 Entity31 0 0
549 25430 Entity32 0 0
549 25432 Entity33 7195 0
910 50910 Entity34 0 0
911 50911 Entity35 0 0
21 13500 Entity36 4016 0
21 13500 Entity36 4020 0
21 13500 Entity36 4022 0
21 13500 Entity36 4024 0
21 13500 Entity36 4028 0
21 13500 Entity36 7016 0
16 11202 Entity37 0 002 0
16 11201 Entity37 0 001 0
16 11200 Entity38 0 30918000
16 11200 Entity38 0 31918000
16 11200 Entity38 0 32110000
AcctTranslate2014
NewAcct SSAcct NewDEpt Fac
10111500 111200010 000 0
10111600 111200050 000 0
10111700 111550010 000 0
10113092 111050450 000 0
10115090 111050010 000 0
FROM GLENTRY
LEFT OUTER JOIN EntityTranslate2014
ON GLENTRY.Fac = EntityTranslate2014.Fac
LEFT OUTER JOIN AcctTranslate2014
ON CONVERT(VARCHAR(8), GLENTRY.Acct) = AcctTranslate2014.SSAcct
There's no relation defined between EntityTranslate2014 and AcctTranslate2014. If there's more than one record in either table for the corresponding record in GLENTRY, then those two tables will effectively cross-join with each other. For example, if a single GLENTRY joins to two records in EntityTranslate2014 and two records in AcctTranslate2014, then you'll get 4 records, one for each possible combination. That's simply how JOIN is defined.
If you know that this is happening and you know there's actually no relation, and you just want, say, for each record in GLENTRY the first record in EntityTranslate2014 to match to the first record in AcctTranslate2014, and the second record in EntityTranslate2014 to match to the second record in AcctTranslate2014 and so on, you can do what I've heard called a "ZIP JOIN":
FROM GLENTRY
LEFT OUTER JOIN (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY Fac ORDER BY <SomeField>) row_order
FROM EntityTranslate2014) ET2014
ON GLENTRY.Fac = ET2014.Fac
LEFT OUTER JOIN (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY SSAcct ORDER BY <SomeField>) row_order
FROM AcctTranslate2014) AT2014
ON CONVERT(VARCHAR(8), GLENTRY.Acct) = AT2014.SSAcct
AND AT2014.row_order = ET2014.row_order
Obviously, don't use SELECT *; this is just an example. So, what this is doing is assigning some order to each OUTER table, and them matching them up with each other. Thus, each record in each OUTER table will only show up once. If there's a mis-match, then the records from the other table will appear as NULLs.
The other common alternative is to simply return the first record for each OUTER table, so that you're guaranteed to only have one GLENTRY record since each OUTER table only contributes one or zero records for each key field.
If that doesn't work for your purposes, then you'll probably need to use two queries, and will need to do the matching in your application.
You can use a Correlated Subquery to "loop" through each row in one table comparing it to rows in another table without actually writing loop logic (which should be avoided in SQL). The rows in the inner query are compared to each row in the outer query based on the where predicate. Correlated Subqueries also allow you to filter the WHERE clause by the TOP 1 if more than 1 record would be returned in the WHERE clause query (as in the code below). This is just a brief example, as I don't have time to write out the code in its entirety, but it may help.
SELECT Entity
FROM EntityTranslate2014 ent
WHERE ent.AcctEnd <> ''
AND AcctEnd = (SELECT TOP 1 SUBSTRING(glt.Acct,6,3)
FROM Glentry glt
WHERE glt.fac = ent.fac
AND glt.Year = 2014
AND glt.Period = 11
ORDER BY glt.Fac, glt.Yearz, glt.Period)
In this example, each record from the EntityTranslate2014 table is compared to the results of the inner query based on the predicate that Glentry.Fac = EntityTraslate2014.fac. Hope that's helpful.
For more information on Correlated Subqueries, check out the following link.
https://technet.microsoft.com/en-us/library/ms187638%28v=sql.105%29.aspx
Updated...
You can use ROW_NUMBER to count sequences in the joined results, and ORDER BY to sort them so that the row you want is first in that sequence.
Thank you for posting the loop construct, I think I was able to approximate it's function with a series of CTEs(WITH alias as (...)). I'm not sure that I got all your table/field names correct, but this should be close to functional. A major guess on my part was how the "first" entity should be determined, you may need to tune the order by in the row number functions in the CTEs.
WITH ENTFIND AS (
SELECT
EntityTranslate2014.Fac,
EntityTranslate2014.Acct,
EntityTranslate2014.AcctEnd,
EntityTranslate2014.Entity,
EntityTranslate2014.SSDept,
EntityTranslate2014.Entity,
ROW_NUMBER() OVER (PARTITION BY Fac, Acct, AcctEnd ORDER BY Fac, Acct, AcctEnd, Entity) as E1Sort
FROM
EntityTranslate2014
),
E2 AS (
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY Fac, Acct, AcctEnd ORDER BY Fac, Acct, AcctEnd, Entity) as E2Sort
FROM
ENTFIND
WHERE
AcctEnd <> 0
),
E3 AS (
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY Fac, Acct, AcctEnd ORDER BY Fac, Acct, AcctEnd, Entity) as E3Sort
FROM
ENTFIND
WHERE
SSDept <> 0
),
E4 AS (
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY Fac, Acct, AcctEnd ORDER BY Fac, Acct, AcctEnd, Entity) as E4Sort
FROM
ENTFIND
WHERE
Acct = 0
AND
AcctEnd = ''
AND
SSDept = 0
)
SELECT
GLENTRY.Fac + GLENTRY.Rundt + GLENTRY.Jrnllog AS UniqueID,
GLENTRY.Fac AS Fac,,
E1.Entity,
E2.Entity,
E3.Entity,
E4.Entity,
COALESCE(E1.Entity,E2.Entity,E3.Entity,E4.Entity) as 1stFoundEntity,
(CASE WHEN
EntityTranslate2014.AcctEnd <> '' AND EntityTranslate2014.AcctEnd = SUBSTRING(GLENTRY.Acct,6,3)
THEN
EntityTranslate2014.Entity
ELSE
CASE WHEN
EntityTranslate2014.AcctEnd <> 0 AND EntityTranslate2014.Acct = GLENTRY.Acct
THEN
EntityTranslate2014.Entity
ELSE
CASE WHEN
EntityTranslate2014.SSDept <> 0 AND EntityTranslate2014.SSDept = SUBSTRING(GLENTRY.Acct,1,4)
THEN
EntityTranslate2014.Entity
ELSE
CASE WHEN
EntityTranslate2014.SSDept = 0
AND
EntityTranslate2014.AcctEnd = ''
AND
EntityTranslate2014.Acct = 0
THEN
EntityTranslate2014.Entity
ELSE
''
END
END
END
END)
AS NEWEntity,
(CASE WHEN AcctTranslate2014.Fac = GLENTRY.Fac OR AcctTranslate2014.Fac = '0'
THEN
AcctTranslate2014.NEWDept
ELSE
Null
END)
AS Department,
(CONVERT(DATETIME,GLENTRY.Period + '/01/' +
CASE WHEN
CONVERT(NVARCHAR(4),GLENTRY.Yearz) = ''
THEN
'2014'
ELSE
GLENTRY.Yearz
END)
AS YEARPER,
GLENTRY.Acct) AS SSAcct,
CONVERT(NVARCHAR(20),
CASE WHEN
AcctTranslate2014.Fac = GLENTRY.Fac OR AcctTranslate2014.Fac = '0'
THEN
AcctTranslate2014.NEWAcct
ELSE
Null
END) AS NEWAccount,
GLENTRY.Rundt,
GLENTRY.Jrnlid,
GLENTRY.Amount,
GLENTRY.Dc,
GLENTRY.Ref,
GLENTRY.Refdt,
CONVERT(NVARCHAR(100),'Import of SS ' + CONVERT(VARCHAR(2),GLENTRY.Period) + '/' + CONVERT(VARCHAR(4),GLENTRY.Yearz) + ' GL activity') AS Descr,
GLENTRY.Invnr,
GLENTRY.Jrnllog,
ROW_NUMBER() OVER(PARTITION BY GLENTRY.Fac, GLENTRY.Yearz, GLENTRY.Period, GLENTRY.Pagez, GLENTRY.Acct, GLENTRY.Rundt, GLENTRY.Jrnlid,
GLENTRY.Amount, GLENTRY.Dc, GLENTRY.Ref, GLENTRY.Refdt, GLENTRY.Descr, GLENTRY.Invnr, GLENTRY.Origfac, GLENTRY.Jrnllog, GLENTRY.Seq
ORDER BY GLENTRY.Fac, GLENTRY.Yearz, GLENTRY.Period) AS m
FROM
GLENTRY
LEFT JOIN
ENTFIND E1 ON GLENTRY.Fac = E1.Fac
AND SUBSTRING(GLENTRY.Acct,6,3) = E1.AcctEnd
AND E1Sort = 1
LEFT JOIN
E2 ON GLENTRY.Fac = E2.Fac
AND GLENTRY.Acct = E2.Acct
AND E2.E2Sort = 1
LEFT JOIN
E3 ON GLENTRY.Fac = E3.Fac
AND SUBSTRING(GLENTRY.Acct,1,4) = E3.SSDept
AND E3.E3Sort = 1
LEFT JOIN
E4 ON GLENTRY.Fac = E4.Fac
AND E4.E4Sort = 1
LEFT OUTER JOIN
EntityTranslate2014 ON GLENTRY.Fac = EntityTranslate2014.Fac
LEFT OUTER JOIN
AcctTranslate2014 ON CONVERT(VARCHAR(8),GLENTRY.Acct) = AcctTranslate2014.SSAcct
WHERE
GLENTRY.Yearz = 2014 AND GLENTRY.Period = 11
I want to thank everyone for their ideas while I tried to get my query to work. I ended up with following solution. Note, for the sake of brevity, I only included the code for determining the Entity field. It's not pretty and I'm sure it's optimal, but it works.
Thanks again for all of your help!!
CASE WHEN
(SELECT
BET.Entity
FROM
BET
WHERE
GL.Fac = BET.Fac
AND
BET.AcctEnd <> ''
AND
BET.AcctEnd = SUBSTRING(CONVERT(NVARCHAR(8),GL.Acct),6,3))
IS NOT Null
THEN
(SELECT
BET.Entity
FROM
SOSViews.dbo.BI360EntityTranslate2014 BET
WHERE
GL.Fac = BET.Fac AND BET.AcctEnd <> ''
AND
BET.AcctEnd = SUBSTRING(CONVERT(NVARCHAR(8),GL.Acct),6,3))
ELSE
CASE WHEN
(SELECT
BET.Entity
FROM
SOSViews.dbo.BI360EntityTranslate2014 BET
WHERE
GL.Fac = BET.Fac
AND
BET.SOSDept <> 0
AND
BET.SOSDept = SUBSTRING(CONVERT(NVARCHAR(8),GL.Acct),1,4))
IS NOT Null
THEN
(SELECT
BET.Entity
FROM
BET
WHERE
GL.Fac = BET.Fac
AND
BET.SOSDept <> 0
AND
BET.SOSDept = SUBSTRING(CONVERT(NVARCHAR(8),GL.Acct),1,4))
ELSE
CASE WHEN
(SELECT
BET.Entity
FROM
BET
WHERE
GL.Fac = BET.Fac
AND
BET.SOSDept = 0 AND BET.AcctEnd = '' AND BET.Acct = 0)
IS NOT Null
THEN
(SELECT
BET.Entity
FROM
BET
WHERE
GL.Fac = BET.Fac
AND
BET.SOSDept = 0 AND BET.AcctEnd = '' AND BET.Acct = 0)
ELSE
'No Entity Translation'
END
END
END)
AS Entity,
Note: Although it may not be directly applicable to the OP's question, sometimes if there are too many rows in a join, it is as simple as joining on the wrong column. This just happened to me....
I'm using SQL Server Express (with advanced services), version 10.50.1600.1.
I need to use a UNPIVOT to create multiple rows from a single ROW, and also need to use JOINS, to get fields from master data tables.
I can make 2 working but separate SELECT statements. The first is the UNPIVOT, the second contains the JOINs. But I simply cannot make them work together! When I put the UNPIVOT followed by the JOINs, I'm always getting error 8156 (Column was specified multiple times) or 4104 (The multi-part identifier could not be bound)...
Sample data is in this SQL Fiddle: http://sqlfiddle.com/#!2/452de/1
Here's the sample data
Table TIMESHEET_LINE
PROJECT_ID DATE1 DATE7 HOUR1 HOUR2 HOUR3 HOUR4 HOUR5 HOUR6 HOUR7
16 2011-10-03 2011-10-09 0 0 0,5 0 0 0 0
18 2011-10-03 2011-10-09 0 0 0,01111111 0 0 0 0
18 2011-10-03 2011-10-09 0 0 0,001944444 0 0 0 0
28 2011-10-03 2011-10-09 0 0 0 2 0 0 0
13 2011-10-03 2011-10-09 0 0 0 0 0 0 0
18 2011-10-03 2011-10-09 0 0 0 0 1,250556 0 0
18 2011-10-03 2011-10-09 0 0 0 0 0,7141666 0 0
Table Project
Table PROJECT
PROJECT_ID PROJECT_NUMBER PROJECT_NAME
13 30013 Control Venta Negativa
16 24464 Zonas de Transporte
18 PRBRCOM2012_12 Garantia
28 24466 Embalagens Retornáveis
The expected output is:
PROJECT_NUMBER PROJECT_NAME DATE HOUR
30013 Control Venta Negativa 2011-10-03 0
30013 Control Venta Negativa 2011-10-04 0
30013 Control Venta Negativa 2011-10-05 0,5
30013 Control Venta Negativa 2011-10-06 0
30013 Control Venta Negativa 2011-10-07 0
30013 Control Venta Negativa 2011-10-08 0
30013 Control Venta Negativa 2011-10-09 0
PRBRCOM2012_12 Garantia 2011-10-03 0
PRBRCOM2012_12 Garantia 2011-10-04 0
PRBRCOM2012_12 Garantia 2011-10-05 0,01111111
PRBRCOM2012_12 Garantia 2011-10-06 0
PRBRCOM2012_12 Garantia 2011-10-07 0
PRBRCOM2012_12 Garantia 2011-10-08 0
PRBRCOM2012_12 Garantia 2011-10-09 0
The SQL statement to UNPIVOT the TIMESHEET_LINE table:
SELECT
[USER_ID],
[PROJECT_ID],
[TASK_GROUP_ID],
[TASK_ID],
DATEADD
(
DAY,
CAST( RIGHT([WeekDay],1)
AS int) - 1,
Date1
) As 'Date',
SUM(Hours) AS 'Hours'
FROM [aceproject].[dbo].[TIMESHEET_LINE]
UNPIVOT
(
Hours for [WeekDay] in (HOUR1, HOUR2, HOUR3, HOUR4, HOUR5, HOUR6, HOUR7)
) upvt
WHERE
[USER_ID] = '18'
GROUP BY
[USER_ID],
[PROJECT_ID],
[TASK_GROUP_ID],
[TASK_ID],
[WeekDay],
[Date1]
The SQL Statement to JOIN the tables:
SELECT
TSL.PROJECT_ID,
P.PROJECT_NUMBER,
P.PROJECT_NAME
FROM [TIMESHEET_LINE] AS TSL
INNER JOIN [aceproject].[dbo].[PROJECT] AS P with (nolock) ON P.PROJECT_ID = TSL.PROJECT_ID
I tried to put them together on several ways. First by using JOINs and UNPIVOT in the same SELECT statement:
SELECT
P.PROJECT_NUMBER,
P.PROJECT_NAME,
TSL.[USER_ID],
TSL.[PROJECT_ID],
TSL.[TASK_GROUP_ID],
TSL.[TASK_ID],
DATEADD
(
DAY,
CAST( RIGHT(upvt.[WeekDay],1)
AS int) - 1,
TSL.Date1
) As 'Date',
SUM(upvt.Hours) AS 'Hours'
FROM [TIMESHEET_LINE] AS TSL
INNER JOIN PROJECT AS P with (nolock) ON P.PROJECT_ID = TSL.PROJECT_ID
UNPIVOT
(
Hours for [WeekDay] in (HOUR1, HOUR2, HOUR3, HOUR4, HOUR5, HOUR6, HOUR7)
) upvt
WHERE
TSL.[USER_ID] = '18'
GROUP BY
TSL.[USER_ID],
TSL.[PROJECT_ID],
TSL.[TASK_GROUP_ID],
TSL.[TASK_ID],
upvt.[WeekDay],
TSL.[Date1]
Also tried selecting from the separate statements:
SELECT
Project_ID,
Client_Country,
Project_Create_By,
Resource_Country,
Resource_IPN,
DATEADD
(
DAY,
CAST( RIGHT([WeekDay],1)
AS int) - 1,
Date1
) As 'Date',
Hours AS 'Hours'
FROM
(
SELECT
TSL.[USER_ID],
TSL.[PROJECT_ID],
TSL.[TASK_GROUP_ID],
TSL.[TASK_ID],
TSL.PROJECT_ID AS 'Project_ID',
Left(C.CLIENT_NAME,2) AS 'Client_Country',
LTRIM(PU.USERNAME) AS 'Project_Create_By',
LEFT(UG1.USER_GROUP_NAME,2) AS 'Resource_Country',
LTRIM(U.USERNAME) AS 'Resource_IPN',
TSL.DATE1,
TSL.HOUR1,
TSL.HOUR2,
TSL.HOUR3,
TSL.HOUR4,
TSL.HOUR5,
TSL.HOUR6,
TSL.HOUR7
FROM [aceproject].[dbo].[TIMESHEET_LINE] AS TSL
INNER JOIN [aceproject].[dbo].[PROJECT] AS P with (nolock) ON P.PROJECT_ID = TSL.PROJECT_ID
LEFT JOIN CLIENT AS C with (nolock) ON C.CLIENT_ID = P.CLIENT_ID
LEFT JOIN USERS AS PU with (nolock) ON (PU.COMPANY_ID = P.COMPANY_ID and PU.USER_ID = P.PROJECT_CREATOR_ID)
LEFT JOIN USERS AS U with (nolock) ON U.USER_ID = TSL.USER_ID
LEFT JOIN USER_GROUP AS UG1 with (nolock) ON (UG1.COMPANY_ID = U.COMPANY_ID and UG1.USER_GROUP_ID = U.USER_GROUP_ID)
) d
UNPIVOT
(
Hours for [WeekDay] in (HOUR1, HOUR2, HOUR3, HOUR4, HOUR5, HOUR6, HOUR7)
) upvt
Also tried the opposite, with the UNPIVOT as sub SELECT.
But nothing worked.
Thanks in advance!
Ok, I sorted it out, finally! =)
First you make the JOIN, and then you make a nested select over it:
SELECT TOP 100
TIMESHEET_LINE_ID,
PROJECT_NUMBER,
DATEADD
(
DAY,
CAST( RIGHT([WeekDay],1)
AS int) - 1,
Date1
) As 'Date',
Hours AS 'Hours'
FROM
(
SELECT
P.PROJECT_NUMBER,
TSL.TIMESHEET_LINE_ID,
TSL.DATE1,
TSL.HOUR1,
TSL.HOUR2,
TSL.HOUR3,
TSL.HOUR4,
TSL.HOUR5,
TSL.HOUR6,
TSL.HOUR7
FROM
[aceproject].[dbo].[TIMESHEET_LINE] AS TSL
INNER JOIN PROJECT AS P with (nolock) ON P.PROJECT_ID = TSL.PROJECT_ID
) d
UNPIVOT
(
Hours for [WeekDay] in (HOUR1, HOUR2, HOUR3, HOUR4, HOUR5, HOUR6, HOUR7)
) upvt
I have three table in SQL Server 2008:
Students
StudentId Name
1 Ghanshyam
2 John
3 Pravin
Exams
ExamId ExamName
1 English
2 Math
3 SS
4 Mechanical
Marks
MarksId StudentId ExamId Marks
1 1 1 90
2 1 2 45
3 1 3 89
4 1 4 56
5 1 5 93
I want to get result display in following format:
Name English Math SS Mechnical
Ghanshyam 90 45 89 56
John 89 38 78 87
Pravin 98 40 48 38
How can I get the above result based on above three table
This is an example of Pivot tables. See
http://msdn.microsoft.com/en-us/library/ms177410.aspx
for the explanation of how to do it in MS SQL Server. Note that it is also possible to do this with standard SQL, though a bit more complicated.
Take a look at the pivot operator / Complex pivot example:
http://msdn.microsoft.com/en-us/library/ms177410.aspx
VendorID is your Name, EmpX your subjects.
Why don't you try something like this, if you do not want a pivot table?
SELECT s.Name,
SUM(CASE WHEN e.ExamName = 'English' THEN m.Marks ELSE 0 END)
/ NULLIF(COUNT(CASE WHEN e.ExamName = 'English' THEN 1 ELSE 0 END), 0) as English,
SUM(CASE WHEN e.ExamName = 'Math' THEN m.Marks ELSE 0 END)
/ NULLIF(COUNT(CASE WHEN e.ExamName = 'Math' THEN 1 ELSE 0 END), 0) as Math,
SUM(CASE WHEN e.ExamName = 'SS' THEN m.Marks ELSE 0 END)
/ NULLIF(COUNT(CASE WHEN e.ExamName = 'SS' THEN 1 ELSE 0 END), 0) as SS,
SUM(CASE WHEN e.ExamName = 'Mechanical' THEN m.Marks ELSE 0 END)
/ NULLIF(COUNT(CASE WHEN e.ExamName = 'Mechanical' THEN 1 ELSE 0 END), 0) as Mechanical
FROM students s, marks m, exams e
WHERE m.StudentID = s.StudentID
AND m.ExamID = e.ExamID
I currently have a table (SQL Server 2005) that logs the visits against my web app, and I want to put together some code to report (and display a visualization) of that traffic. What I want is to display the number of visits during each ten-minute interval over the last 24 hours.
I have a query that does just that, but there are ten-minute intervals during which there are no visits, and I would like to adjust my query to display a zero count for those intervals. I imagine I could come up with something using cursors, but I'd rather not use them if I can avoid it.
Here is the query so far:
DECLARE #time int
DECLARE #interval int
SELECT #time=96
SELECT #interval=10
SELECT interval,
COUNT(*) AS requestCount,
DATEDIFF(MINUTE,DATEADD(HOUR,-1*#time-1,getDate()),interval)/#interval AS intervalPos
FROM
(SELECT DATEADD(MINUTE, FLOOR(DATEDIFF(MINUTE, getDate(), requestBegin) / (#interval*1.0)) * #interval,getDate())
FROM [track_pageSubmit] WHERE requestBegin IS NOT NULL AND DATEDIFF(HOUR,requestBegin,getDate()) < #time) AS I(interval)
GROUP BY interval ORDER BY interval
Here is the table structure:
CREATE TABLE [dbo].[Track_PageSubmit](
[id] [int] IDENTITY(1,1) NOT NULL,
[popid] [int] NOT NULL,
[section] [varchar](30) NULL,
[page] [int] NULL,
[requestBegin] [datetime] NULL,
[requestEnd] [datetime] NULL,
[rendered] [datetime] NULL,
[postBegin] [datetime] NULL,
[postEnd] [datetime] NULL
)
And here is what some of the records look like:
INSERT INTO track_pageSubmit (popid,section,page,requestbegin,requestend,rendered,postbegin,postend)
SELECT '2393712','Main_Can_Eng','10','2010-01-22 10:22:08.287','2010-01-22 10:22:08.330',NULL,'2010-01-22 10:22:09.503','2010-01-22 10:22:09.627' UNION
SELECT '2393712','Main_Can_Eng','11','2010-01-22 10:22:09.660','2010-01-22 10:22:09.770',NULL,'2010-01-22 10:22:10.973','2010-01-22 10:22:11.050' UNION
SELECT '2393712','Main_Can_Eng','12','2010-01-22 10:22:11.080','2010-01-22 10:22:11.143',NULL,'2010-01-22 10:22:12.503','2010-01-22 10:22:12.567' UNION
SELECT '2394478','main','21','2010-01-21 10:38:54.057','2010-01-21 10:38:54.117','2010-01-21 10:38:54.487','2010-01-21 10:38:55.633','2010-01-21 10:38:55.697' UNION
SELECT '2394478','main','22','2010-01-21 10:38:55.757','2010-01-21 10:38:55.820','2010-01-21 10:38:56.197','2010-01-21 10:38:57.477','2010-01-21 10:38:57.570' UNION
SELECT '2394478','main','23','2010-01-21 10:38:57.617','2010-01-21 10:38:57.993','2010-01-21 10:38:58.367','2010-01-21 10:38:59.397','2010-01-21 10:38:59.493' UNION
SELECT '2394478','main','25','2010-01-21 10:38:59.553','2010-01-21 10:38:59.617','2010-01-21 10:38:59.993','2010-01-21 10:39:01.227','2010-01-21 10:39:01.303' UNION
SELECT '2394478','main','26','2010-01-21 10:39:01.350','2010-01-21 10:39:01.477','2010-01-21 10:39:01.860','2010-01-21 10:39:02.787','2010-01-21 10:39:02.867' UNION
SELECT '2394478','main','27','2010-01-21 10:39:02.930','2010-01-21 10:39:03.007','2010-01-21 10:39:03.400','2010-01-21 10:39:04.147','2010-01-21 10:39:04.460' UNION
SELECT '2394478','main','28','2010-01-21 10:39:04.507','2010-01-21 10:39:05.147','2010-01-21 10:39:05.790','2010-01-21 10:39:19.413','2010-01-21 10:39:19.477' UNION
SELECT '2393754','exp46_cex','1','2010-01-22 12:40:56.563','2010-01-22 12:40:56.640',NULL,'2010-01-22 12:40:58.657','2010-01-22 12:40:58.733' UNION
SELECT '2393754','exp46_cex','2','2010-01-22 12:40:58.750','2010-01-22 12:40:58.780',NULL,'2010-01-22 12:41:15.623','2010-01-22 12:41:15.657' UNION
SELECT '2393754','additionalComments','1','2010-01-22 12:41:15.670','2010-01-22 12:41:15.733',NULL,'2010-01-22 12:41:19.000','2010-01-22 12:41:19.030' UNION
SELECT '2393802','main','2','2010-01-22 12:44:50.857','2010-01-22 12:44:50.933',NULL,'2010-01-22 12:44:53.497','2010-01-22 12:44:53.557' UNION
SELECT '2393802','main','3','2010-01-22 12:44:53.590','2010-01-22 12:44:53.667',NULL,'2010-01-22 12:44:56.370','2010-01-22 12:44:56.730'
Bonus points (in the form of extra thanks from me) to anyone who can change the query so that I can also report distinct popids per interval (in addition to total requests).
Thanks!
-- Because your sample data spans 27 hours:
DECLARE
#hours TINYINT,
#minute_interval TINYINT,
#start SMALLDATETIME;
SELECT
#hours = 27,
#minute_interval = 10,
#start = '20100122 13:00';
;WITH x AS
(
SELECT TOP (#hours * (60 / #minute_interval))
n = ROW_NUMBER() OVER
(ORDER BY column_id)
FROM msdb.sys.columns
),
intervals(boundary) AS
(
SELECT CONVERT
(
SMALLDATETIME,
DATEADD(MINUTE, (-n * #minute_interval), #start)
)
FROM x
)
SELECT
i.boundary,
RequestCount = COUNT(d.id),
DistinctPopIDs = COUNT(DISTINCT d.popid)
FROM
intervals AS i
LEFT OUTER JOIN
dbo.Track_PageSubmit AS d
ON d.requestBegin >= i.boundary
AND d.requestBegin < DATEADD(MINUTE, #minute_interval, i.boundary)
GROUP BY i.boundary
ORDER BY i.boundary;
Easy way to do this is to use a CTE and make a helper table with the start time interval, then just join to that table in the main query using between.
Did that make sense? I'll work on some example code in a bit.
DECLARE #time int
DECLARE #interval int
SELECT #time=96
SELECT #interval=10
DECLARE #count int
SELECT #count=1
;WITH daterange AS
(
SELECT 1 as [id], Max(requestbegin) as maxr, Min(requestBegin) as minr
FROM track_pagesubmit
), intervals as
(
SELECT #count AS interval, minr as intervalpos
FROM daterange
WHERE [id] = 1
UNION ALL
SELECT interval+1 AS interval,
DATEADD(MINUTE,#interval,intervalpos) as intervalpos
FROM intervals
JOIN daterange on [ID] = 1
WHERE DATEADD(MINUTE,#interval,intervalpos) < maxr
)
SELECT interval, intervalpos,
COUNT(DISTINCT track_pagesubmit.popid) as popcount,
COUNT(track_pagesubmit.id AS requestcount
FROM intervals
LEFT JOIN track_pagesubmit ON requestbegin IS NOT NULL
AND requestBegin BETWEEN intervalpos AND DATEADD(ns,-1,DATEADD(MINUTE,#interval,intervalpos))
GROUP BY interval, intervalpos
OPTION (MAXRECURSION 200)
The recursive CTE always seems to outperform the numbers table, but both methods are traditionally used for this.
This is a bit rough, but should work for you:
WITH Nbrs_2( n ) AS ( SELECT 1 UNION SELECT 0 ),
Nbrs_1( n ) AS ( SELECT 1 FROM Nbrs_2 n1 CROSS JOIN Nbrs_2 n2 ),
Nbrs_0( n ) AS ( SELECT 1 FROM Nbrs_1 n1 CROSS JOIN Nbrs_1 n2 ),
Nbrs ( n ) AS ( SELECT 1 FROM Nbrs_0 n1 CROSS JOIN Nbrs_0 n2 )
select n.n as TenMinuteInterval, count(case when t.requestBegin is null then null else 1 end) as Count
from (
SELECT n - 1 as n
FROM (SELECT ROW_NUMBER() OVER (ORDER BY n)
FROM Nbrs) D ( n )
WHERE n <= 144
) n
left outer join track_pageSubmit t on n.n = floor((cast(requestBegin - convert(int, requestBegin) as decimal(10,3)) % 1) * 144)
and requestBegin between '2010-01-21' and '2010-01-22'
group by n.n
Output:
TenMinuteInterval Count
-----------------------
0 0
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 0
10 0
11 0
12 0
13 0
14 0
15 0
16 0
17 0
18 0
19 0
20 0
21 0
22 0
23 0
24 0
25 0
26 0
27 0
28 0
29 0
30 0
31 0
32 0
33 0
34 0
35 0
36 0
37 0
38 0
39 0
40 0
41 0
42 0
43 0
44 0
45 0
46 0
47 0
48 0
49 0
50 0
51 0
52 0
53 0
54 0
55 0
56 0
57 0
58 0
59 0
60 0
61 0
62 0
63 7
64 0
65 0
66 0
67 0
68 0
69 0
70 0
71 0
72 0
73 0
74 0
75 0
76 0
77 0
78 0
79 0
80 0
81 0
82 0
83 0
84 0
85 0
86 0
87 0
88 0
89 0
90 0
91 0
92 0
93 0
94 0
95 0
96 0
97 0
98 0
99 0
100 0
101 0
102 0
103 0
104 0
105 0
106 0
107 0
108 0
109 0
110 0
111 0
112 0
113 0
114 0
115 0
116 0
117 0
118 0
119 0
120 0
121 0
122 0
123 0
124 0
125 0
126 0
127 0
128 0
129 0
130 0
131 0
132 0
133 0
134 0
135 0
136 0
137 0
138 0
139 0
140 0
141 0
142 0
143 0