How to do join for my sitaution - sql-server-2005

i have two select statement from two different table and the common join field a datefield
one date field name is JobFinishedDate and it is from MyJobs table and another date field name is createddate and it is from DailyFinishJobsHistory table
here is my two independent sql
sql 1
SELECT CONVERT(varchar,createddate,101) as [Date],
SUM([No of Jobs]) as [No of Jobs],
SUM([Turnaround Time]) as [Turnaround Time],
SUM([One Day Per]) as [One Day Per],
ROUND((SUM([No of Jobs]) * SUM([Turnaround Time])),2) as [TOTAL hours]
from DailyFinishJobsHistory d
WHERE CONVERT(varchar,createddate,112)>='20131015' AND CONVERT(varchar,createddate,112)<='20131021'
group by createddate
sql 2
Select
convert(varchar,JobFinishedDate,112) as JobFinishedDate
, Count(*) [Number of techs]
From
(
select
convert(varchar,JobFinishedDate,112) JobFinishedDate,Specialist
from MyJobs
where convert(varchar,JobFinishedDate,112)>='20131015'
and convert(varchar,JobFinishedDate,112) <='20131021'
and JobState='FINISHED'
group by convert(varchar,JobFinishedDate,112) , Specialist
) t1
Group By
JobFinishedDate
now i have to join. i tried like this way but right syntax is not coming to my mind to join this way.
SELECT CONVERT(varchar,createddate,101) as [Date],
SUM([No of Jobs]) as [No of Jobs],
SUM([Turnaround Time]) as [Turnaround Time],
SUM([One Day Per]) as [One Day Per],
ROUND((SUM([No of Jobs]) * SUM([Turnaround Time])),2) as [TOTAL hours],
(
Select
convert(varchar,JobFinishedDate,112) as JobFinishedDate
, Count(*) [Number of techs]
From
(
select
convert(varchar,JobFinishedDate,112) JobFinishedDate,Specialist
from bbajobs
where convert(varchar,JobFinishedDate,112)>='20131015'
and convert(varchar,JobFinishedDate,112) <='20131021'
and JobState='FINISHED'
group by convert(varchar,JobFinishedDate,112) , Specialist
) t1
Group By
JobFinishedDate
) a
from DailyFinishJobsHistory d
WHERE CONVERT(varchar,createddate,112)>='20131015' AND CONVERT(varchar,createddate,112)<='20131021'
group by createddate
so please help me bit to build the join. thanks
EDIT
i tried this script also but [Number of techs] is getting NULL
SELECT CONVERT(varchar,createddate,101) as [Date],
SUM([No of Jobs]) as [No of Jobs],
SUM([Turnaround Time]) as [Turnaround Time],
SUM([One Day Per]) as [One Day Per],
ROUND((SUM([No of Jobs]) * SUM([Turnaround Time])),2) as [TOTAL hours],
(
SELECT
--CONVERT(varchar,JobFinishedDate,112) as JobFinishedDate,
COUNT(*) [Number of techs]
From
(
SELECT CONVERT(varchar,JobFinishedDate,112) JobFinishedDate,
Specialist
FROM bbajobs
WHERE d.createddate=JobFinishedDate AND
JobState = 'FINISHED'
GROUP BY CONVERT(varchar,JobFinishedDate,112), Specialist
) t1
GROUP BY JobFinishedDate
) [Number of techs]
FROM DailyFinishJobsHistory d
WHERE CONVERT(varchar,createddate,112) >= '20131015' AND CONVERT(varchar,createddate,112) <= '20131021'
GROUP BY createddate

Something like this should do the trick:
SELECT *
FROM
(
SELECT CONVERT(varchar,createddate,112) as [Date],
SUM([No of Jobs]) as [No of Jobs],
SUM([Turnaround Time]) as [Turnaround Time],
SUM([One Day Per]) as [One Day Per],
ROUND((SUM([No of Jobs]) * SUM([Turnaround Time])),2) as [TOTAL hours]
FROM DailyFinishJobsHistory
WHERE CONVERT(varchar,createddate,112) >= '20131015'
AND CONVERT(varchar,createddate,112) <= '20131021'
GROUP BY createddate
) A
JOIN
(
SELECT
JobFinishedDate,
COUNT(*) [Number of techs]
From
(
SELECT CONVERT(varchar,JobFinishedDate,112) JobFinishedDate
FROM MyJobs
WHERE CONVERT(varchar,JobFinishedDate,112) >= '20131015'
AND CONVERT(varchar,JobFinishedDate,112) <='20131021'
AND JobState = 'FINISHED'
) t1
GROUP BY JobFinishedDate
) B
ON B.JobFinishedDate = A.[Date]
See joining two select statements for a simpler example.

Related

Query to show each day data when we have records for 2 distinct dates

I have a SQL Table as below:
DEVICE ID
STATUS
Created Date
Device 1
ACTIVE
1/10/2022
Device 1
INACTIVE
5/10/2022
Now I need to write a query to show the status of every day. My Output should be as below:
Device 1 - 1/10/2022 - ACTIVE
Device 1 - 2/10/2022 - ACTIVE
Device 1 - 3/10/2022 - ACTIVE
Device 1 - 4/10/2022 - ACTIVE
Device 1 - 5/10/2022 - INACTIVE
I have tried few queries which does not giving me correct result. So, it would be appreciate if I can get some help on this. Thanks in Advance.
You may try a recursive CTE as the following:
WITH CTE AS
(
SELECT DEVICE_ID, STATUS, Created_Date
FROM table_name
UNION ALL
SELECT C.DEVICE_ID, C.STATUS, DATEADD(DAY, 1, C.Created_Date)
FROM CTE C
WHERE DATEADD(DAY, 1, C.Created_Date) NOT IN (SELECT Created_Date FROM table_name T WHERE T.DEVICE_ID=C.DEVICE_ID AND T.STATUS='INACTIVE')
AND DATEADD(DAY, 1, C.Created_Date)<=GETDATE()
AND STATUS='ACTIVE'
)
SELECT DEVICE_ID, STATUS, Created_Date
FROM CTE
ORDER BY DEVICE_ID, Created_Date
See a demo with extended data sample.
Create a table with every day as a record.
Take the following Device Status dates from YourStatusTable with a self join and rank them with a row_number
Join your status table to the date seed where the rn = 1
with YourStatusTable as (
select 'Device 1' [Device ID], 'ACTIVE' [Status], cast('01-Oct-2022' as date) [Created Date]
union all select 'Device 1' [Device ID], 'INACTIVE' [Status], '05-Oct-2022'
union all select 'Device 1' [Device ID], 'ACTIVE' [Status], '08-Oct-2022'
union all select 'Device 1' [Device ID], 'INACTIVE' [Status], '12-Oct-2022'
union all select 'Device 2' [Device ID], 'ACTIVE' [Status], '20-Oct-2022'
union all select 'Device 2' [Device ID], 'INACTIVE' [Status], '25-Oct-2022'
),
seed as (
select null as n
union all select null
),
dates as (
select dateadd(day,row_number() OVER ( ORDER BY a.n )-1, '-Sep-2022') date_value
from seed a,
seed b,
seed c,
seed d,
seed e,
seed f
),
status_boundaries as (
select
a.[Device ID],
a.[Status],
a.[Created Date],
b.[Created Date] [next_status_date],
row_number() over ( partition by a.[Device ID],a.[Created Date] order by b.[Created Date]) rn
from YourStatusTable a
left join YourStatusTable b on a.[Device ID] = b.[Device ID] and a.[Created Date] < b.[Created Date]
)
select *
from dates
inner join status_boundaries on date_value >= [Created Date]
where ( date_value < next_status_date or next_status_date is null )
and rn = 1

Join Group By Columns Vertically

I have multiple group by queries that I need to be join horizontally. Here is what I have.
Here is what I need. Is this doable?
select
Group,
Count([Total # Records]
from table
select
Group,
Count([Total # Records]
from table
where
[Date] < DATEADD(DAY, -60, getdate())
Use conditional aggregation:
select Group, Count([Total # Records]),
sum(case when [Date] < DATEADD(DAY, -60, getdate() then 1 else 0 end)
from table
group by group;
You can use the conditional aggregation using COUNT aggregate function as follows:
select group,
count([Total # Records]),
count(case when [Date] < DATEADD(DAY, -60, getdate()) then 1 end)
from table
group by group;
COUNT will ignore the null values produced by the conditions so it will give count of the records which fulfills the condition.
Below is script of the solution I ultimately used. A full working copy and sample databae can be found at Fiddle
;with table1CTE
as
(
select
[Groups],
sum([total # records]) as [total # records]
from
tbl1
where
[Groups]
in
(
select
[groups]
from
(
select
[groups],
[total # records]
from
tbl1
) as sourceTbl1
pivot
(sum ([total # records])
for [groups]
in
([Central Business],
[Venture Capital])
) as pvt
)
group by [groups]
),--table1CTE
table2CTE as
(
select
[Groups],
sum([No Action Over 60 Days]) as [No Action Over 60 Days]
from
tbl2
where
[Groups]
in
(
select
[groups]
from
(
select
[groups],
[No Action Over 60 Days]
from
tbl1
) as sourceTbl1
pivot
(sum ([No Action Over 60 Days])
for [groups]
in
([Central Business],
[Venture Capital])
) as pvt
)
group by [groups]
)--table2CTE
select
table1CTE.groups,
table1CTE.[total # records],
table2CTE.[No Action Over 60 Days]
from table1CTE left join table2CTE on table1CTE.[Groups] = table2CTE.[Groups]

How can I join 2 table together?

I'm trying to create a join table with 2 existing tables. something like below:
This is the first table queries and looks like this
https://ibb.co/sg2MXKf
SELECT
DATEPART( week, dbo.Income.IncomeDate ) AS [Week Income],
DATEPART( YEAR, dbo.Income.IncomeDate ) AS [Year],
SUM ( dbo.Income.CardAmount ) AS [Total Card],
SUM ( dbo.Income.CashAmount ) AS [Total Cash],
SUM ( dbo.Income.TipsAmount ) AS [Total Tip],
SUM ( dbo.Income.SalaryAmount ) AS [Total Salary],
SUM ( dbo.Income.Adjustment ) AS [Total Adjustment]
FROM
dbo.Income
GROUP BY
DATEPART( week, dbo.Income.IncomeDate ),
DATEPART( YEAR, dbo.Income.IncomeDate )
ORDER BY
DATEPART(YEAR, dbo.Income.IncomeDate )
And this is the second table queries and looks like this
https://ibb.co/z8sRwpT
SELECT
DATEPART( wk, dbo.Transactions.PaymentMadeOn ) AS [Week],
COUNT (DATEPART( wk, dbo.Transactions.PaymentMadeOn )) AS [Expenses Count],
DATEPART( YEAR, dbo.Transactions.PaymentMadeOn ) AS [Year],
SUM ( dbo.Transactions.PaymentAmount ) AS [Total]
FROM
dbo.Transactions
GROUP BY
DATEPART( wk, dbo.Transactions.PaymentMadeOn ),
DATEPART( YEAR, dbo.Transactions.PaymentMadeOn )
ORDER BY
DATEPART( YEAR, dbo.Transactions.PaymentMadeOn )
What I expected is something this. Both table 1 and 2 combined, and the total expenses added.
https://ibb.co/0DbZLYV
As commented by SO folks, we cannot access the images that describe your expected results. However we understand that you are looking to JOIN the results of both queries that you are showing.
Here is how to do it : you turn each query into a subquery, and you JOIN them together on their common key fields ; in your use case, this must be Year and Week. The ORDER BY clause needs to be moved to the outer query. In the SELECT, WHERE and ORDER BY clauses, you can freely access all the fields from the subqueries, using the aliases that you defined (here A and B).
Sample code (you will have to adapt the SELECT, I cannot tell what you want it to look like) :
SELECT
A.[Week Income],
A.[Year],
A.[Total] - B.[Total Salary] AS [Balance]
...
FROM (
SELECT
DATEPART( week, dbo.Income.IncomeDate ) AS [Week Income],
DATEPART( YEAR, dbo.Income.IncomeDate ) AS [Year],
SUM ( dbo.Income.CardAmount ) AS [Total Card],
SUM ( dbo.Income.CashAmount ) AS [Total Cash],
SUM ( dbo.Income.TipsAmount ) AS [Total Tip],
SUM ( dbo.Income.SalaryAmount ) AS [Total Salary],
SUM ( dbo.Income.Adjustment ) AS [Total Adjustment]
FROM
dbo.Income
GROUP BY
DATEPART( week, dbo.Income.IncomeDate ),
DATEPART( YEAR, dbo.Income.IncomeDate )
) AS A
LEFT JOIN (
SELECT
DATEPART( wk, dbo.Transactions.PaymentMadeOn ) AS [Week],
COUNT (DATEPART( wk, dbo.Transactions.PaymentMadeOn )) AS [Expenses Count],
DATEPART( YEAR, dbo.Transactions.PaymentMadeOn ) AS [Year],
SUM ( dbo.Transactions.PaymentAmount ) AS [Total]
FROM
dbo.Transactions
GROUP BY
DATEPART( wk, dbo.Transactions.PaymentMadeOn ),
DATEPART( YEAR, dbo.Transactions.PaymentMadeOn )
) AS B ON A.[Week Income] = B.[Week] AND A.[Year] = B.[Year]
ORDER BY
A.[Year],
A.[Week Income]

SQL Calculate Percentage in Group By

I have an SQL query that is used as the basis for a report. The report shows the amount of fuel used grouped by Year, Month and Fuel Type. I would like to calculate the percentage of the total for each fuel type, but I'm not having much luck. In order to calculate the percentage of the whole, I need to be able to get the total amount of fuel used regardless of the group it is in and I can't seem to figure out how to do this. Here is my query:
SELECT Year([DT1].[TransactionDate]) AS [Year], Month([DT1].[TransactionDate]) AS [Month], DT1.FuelType, Format(Sum(DT1.Used),"#.0") AS [Total Used],
FROM (SELECT TransactionDate, FuelType, Round([MeterAfter]-[MeterBefore],2) AS Used FROM FuelLog) AS DT1
WHERE (((DT1.TransactionDate) Between [Start Date] And [End Date]))
GROUP BY Year([DT1].[TransactionDate]), Month([DT1].[TransactionDate]), DT1.FuelType
ORDER BY Year([DT1].[TransactionDate]), Month(DT1.TransactionDate), DT1.FuelType;
I tried adding the following as a subquery but I get an error saying the subquery returns more than one result.
(SELECT Sum(Round([MeterAfter]-[MeterBefore],2)) AS Test
FROM Fuellog
WHERE Year([Year]) and Month([Month])
GROUP BY Year([TransactionDate]), Month([TransactionDate]))
Once I get the total of all fuel I will need to divide the amount of fuel used by the total amount of both fuel types. Should I be approaching this a different way?
Try this
SELECT A.[Year]
,A.[Month]
,A.[FuelType]
,A.[Total Used]
,(A.[Total Used] / B.[Total By Year Month]) * 100 AS Percentage
FROM
(
SELECT Year([DT1].[TransactionDate]) AS [Year]
, Month([DT1].[TransactionDate]) AS [Month]
, DT1.FuelType
, Format(Sum(DT1.Used),"#.0") AS [Total Used]
FROM (
SELECT TransactionDate
, FuelType
, Round([MeterAfter]-[MeterBefore],2) AS Used
FROM FuelLog
) AS DT1
WHERE (((DT1.TransactionDate) Between [Start Date] And [End Date]))
GROUP BY Year([DT1].[TransactionDate]), Month([DT1].[TransactionDate]), DT1.FuelType
ORDER BY Year([DT1].[TransactionDate]), Month(DT1.TransactionDate), DT1.FuelType
) A
INNER JOIN
(
SELECT Sum(Round([MeterAfter]-[MeterBefore],2)) AS [Total By Year Month]
, Year([TransactionDate]) AS [Year]
, Month([TransactionDate])) AS [Month]
FROM Fuellog
GROUP
BY Year([TransactionDate])
, Month([TransactionDate]))
) B
ON A.[Year] = B.[Year]
AND A.[Month] = B.[Month]
You need to join to the totals -- something like this (untested might have typos)
SELECT
Year([DT1].[TransactionDate]) AS [Year],
Month([DT1].[TransactionDate]) AS [Month],
DT1.FuelType,
Format(Sum(DT1.Used),"#.0") AS [Total Used],
(Sum(DT1.Used) / FT.Total) * 100 AS Percent
FROM (
SELECT
TransactionDate,
FuelType,
Round([MeterAfter]-[MeterBefore],2) AS Used
FROM FuelLog
) AS DT1
JOIN (
SELECT
Sum(Round([MeterAfter]-[MeterBefore],2)) AS Total
FuelType
FROM Fuellog
WHERE TransactionDate Between [Start Date] And [End Date]
GROUP BY FuelType
) FT ON DT1.FuelType = FT.FeulType
WHERE DT1.TransactionDate Between [Start Date] And [End Date]
GROUP BY Year([DT1].[TransactionDate]), Month([DT1].[TransactionDate]), DT1.FuelType, FT.Total
ORDER BY Year([DT1].[TransactionDate]), Month(DT1.TransactionDate), DT1.FuelType, FT.Total;

SQL query for splitting the period of date into each date for corresponding employee id

I have one table with name "Employee"...It has 3 fields:
empid
from date
todate
I want to split the period of date (dates between from date & to date including both) for the corresponding emp id.
For example here's the table I've got:
emp id from date to date
1 1/1/2011 3/1/2011
2 5/1/2011 5/1/2011
From that I'm want to get this:
1 1/1/2011
1 2/1/2011
1 3/1/2011
2 5/1/2011
What's an SQL query that would do this for me?
You wants... I gives...
;with Employee([emp id],[from date],[to date]) as (
select 1, convert(datetime,'20110101'), convert(datetime,'20110103') union all
select 2, '20010105', '20110105'
)
-- your query below here
select [emp id], [from date] + w.number*1000 + v.number [the date]
from Employee e
inner join master..spt_values w
on w.type='P' and w.number <= datediff(d, [from date], [to date]) % 1000
inner join master..spt_values v
on v.type='P'
and v.number <= 999
and (w.number*1000) + v.number <= datediff(d, [from date], [to date])
order by [emp id], [the date]
Here's a simpler version if you don't ever deal with more than 6 years at a time
select [emp id], [from date] + v.number [the date]
from Employee e
inner join master..spt_values v
on v.type='P'
and v.number <= datediff(d, [from date], [to date])
order by [emp id], [the date]
A solution that uses a recursive CTE (works with SQL Server 2005+):
WITH Employee (emp_id, from_date, to_date) AS (
/* this is just a sample data definition */
SELECT 1, CAST('20110101' AS datetime), CAST('20110103' AS datetime) UNION ALL
SELECT 2, CAST('20110105' AS datetime), CAST('20110105' AS datetime)
),
unrolled AS (
/* and this is the recursive CTE */
SELECT
emp_id,
from_date AS date
FROM Employee
UNION ALL
SELECT
r.emp_id,
DATEADD(day, 1, r.date)
FROM Employee e
INNER JOIN unrolled r
ON e.emp_id = r.emp_id AND e.to_date > r.date
)
SELECT * FROM unrolled
ORDER BY emp_id, date