SQL Statement Issue combining 4 tables to get the correct information to display - sql

I am having trouble figuring this one out. I'm using MS SQL 2008 and trying to add the total tech hours from the unbilled table and the billed tables and group them together. I also need to exclude rows for the billed hours based on the report header on a third table if the billed report is voided. I then need to grab the tech names from a 4th table. The unbilled table is SCQReportLabors which lists all the labor records. SCReportLabors table lists all the billed labor records. SCReports is the billed report header which I need to figure out if the VoidID column is null. ShAgents table holds the tech names. Below is what I currently have and I know it doesn't work but it's what I've got so far. For my output data I woul like a TotalHours column and a TechName column. If I end up with a billed total, unbilled total and techname column I can live with that as well. I've been staring at this for a little while and need some perspective and advice. Thanks in advance for any help.
SELECT a.TotalHours, c.PrefFullName AS TechName
FROM (SELECT SUM(LaborHours)+SUM(OvertimeHours)+SUM(TravelHours) AS TotalHours, TechnicianID
FROM SCReportLabors
LEFT OUTER JOIN SCReports d ON a.ReportID = d.ReportID
WHERE d.VoidID IS NULL
GROUP BY TechnicianID) a
JOIN (SELECT SUM(LaborHours)+SUM(OvertimeHours)+SUM(TravelHours) AS TotalHours, TechnicianID
FROM SCQReportLabors
GROUP BY TechnicianID) b
ON a.TechnicianID = b.TechnicianID
LEFT OUTER JOIN ShAgents c ON a.TechnicianID = c.AgentID
ORDER BY c.PrefFullName

This query should capture all data and handles null hours.
SELECT
A.PrefFullName AS 'TechName',
(ISNULL(B.TotalHours, 0) + ISNULL(C.TotalHours, 0)) AS 'Total Hours'
FROM
ShAgents AS A
LEFT OUTER JOIN
(
SELECT
(
SUM(ISNULL(LaborHours, 0)) +
SUM(ISNULL(OvertimeHours, 0)) +
SUM(ISNULL(TravelHours, 0))
) AS 'TotalHours',
TechnicianID
FROM
SCReportLabors AS tA
LEFT OUTER JOIN SCReports AS tB
ON tA.ReportID = tB.ReportID
WHERE
tB.VoidID IS NULL
GROUP BY
TechnicianID
) AS B
ON A.AgentID = B.TechnicianID
LEFT OUTER JOIN
(
SELECT
(
SUM(ISNULL(LaborHours, 0)) +
SUM(ISNULL(OvertimeHours, 0)) +
SUM(ISNULL(TravelHours, 0))
) AS 'TotalHours',
TechnicianID
FROM
SCQReportLabors
GROUP BY
TechnicianID
) AS C
ON A.AgentID = C.TechnicianID
ORDER BY
A.PrefFullName

I made the two main queries a UNION query and also touched up on JOIN for the VOID column.
SELECT SQ1.TotalHours, SHA.PrefFullName AS TechName
FROM
(
SELECT SUM(TOTALHOURS) AS TotalHours, TechnicianID
(SELECT SUM(LaborHours)+SUM(OvertimeHours)+SUM(TravelHours) AS TotalHours, TechnicianID
FROM SCReportLabors L
JOIN SCReports RPTS
ON L.ReportID = RPTS.ReportID
WHERE RPTS.VoidID IS NULL
GROUP BY TechnicianID)
UNION ALL
(SELECT SUM(LaborHours)+SUM(OvertimeHours)+SUM(TravelHours) AS TotalHours, TechnicianID
FROM SCQReportLabors
GROUP BY TechnicianID
)
) SQ
GROUP BY TechnicianID
JOIN ShAgents SHA
ON SQ.TechnicianID = SHA.AgentID
ORDER BY SHA.PrefFullName

Related

How to join two tables having two common column values and unioning the rest

I'd like to combine Table A and Table B at the link below and end up with Table C. What is the best way to do this in SQL? I've thought about creating a composite key between the tables for LedgerID + Year doing an inner join and then unioning the left and right only data. I'm also curious how to avoid duplicating values across rows like Balance = 50.00 ending up in rows for Tires and Windshield.
Try a full outer join, joining on LedgerID and Year, using coalesce to show Table B's LedgerID/Year when Table A's is NULL:
SELECT
COALESCE(A.LedgerID, B.LedgerID) as LedgerID,
COALESCE(A.Year, B.Year) as Year,
A.Title,
A.Payment,
B.Balance
FROM "Table A" AS A
FULL OUTER JOIN "Table B" AS B ON (A.LedgerID=B.LedgerID AND A.Year=B.Year)
--Please try this Query. Since you have only reference LedgerId and Year, the balance will show 50 for both Tires & Windshield
; with cte_Ledger (LedgerId, [year])
AS
(
Select DISTINCT LedgerId, [year]
From tableA
UNION
Select DISTINCT LedgerId, [year]
From tableB
)
select t.LedgerId
, t.[year]
, t1.Title
, T1.Payments
, t2.Balance
FROM cte_Ledger t
left join tableA t1 on t.LedgerId = t1.LedgerId and t.[year] = t1.[year]
left join tableB t2 on t2.LedgerId = t.LedgerId and t2.[year] = t.[year]
I think so, Above Queries will not help to get expected result.
some misunderstanding is with requirement.
For ledgerid = 22 and Year = 2017, have 2 records in table-A and 1 with Table-B. But in expecting result, Balance 50(Record of table-B) is exists with matched first row of Table-A only. As per above all logic it will be with 2 Records where ledgerid = 22, Year = 2017 and Title with "Tires" & "Windshield".
If required same result as mentioned then need to use recursive CTE or ranking function with order of ID column.
Here is my solution after I loaded the tables, another nested case statement may be need to format out the zero on Ledger 24.
Select
[LedgerID],
[Year],
Case when PayRank = 1 then Title else '' end as Title,
Case when PayRank = 1 then convert(varchar(20),Payments) else '' end as
Payments,
Case when BalRank = 1 then convert(varchar(20),Balance) else '' end as
Balance
from(
SELECT
B.[LedgerID]
,B.[Year]
,Rank()Over(Partition by B.LedgerID,Payments order by
B.LedgerID,B.Year,Title) as PayRank
,isnull([Title],'') as Title
,isnull([Payments],0) as Payments
,Rank()Over(Partition by B.LedgerID,B.Year order by
B.LedgerID,B.Year,Payments) as BalRank
,Balance
FROM [TableB] B
left outer join [TableA] A
on A.LedgerID = B.LedgerID
) Query
order by LedgerID,Year

Insert data in ssrs table in the query

I would like to insert some data in the ssrs table.
I would like to show it like this here:
How can I add these data in my query in SSRS. I have no possibility to change something in the database.
| P1|P2 |P3 |P4 |P5 |P6 |P7 |P8
Group A|84%|87%|81%|81%|79%|96%|86%|88%
Group B|66%|22%|79%|64%|53%|94%|5% |23%
The Problem is:
Last week on wednesday the database did not recorded the data from Group A and Group B. And I have no possibility to correct/add the missing data in the database. And thats why I would like to add these missed data in my query and show it in the report.
My query:
SELECT *
FROM (
Select
intervaldate as Datum
,tsystem.Name as Name
,team as group
,SUM(GoodUnits) As Goods
,SUM(TheoreticalUnits) As Units
from tCount inner join tsystem ON tCount.systemid = tsystem.id
where IntervalDate >= #StartDateTime AND IntervalDate <= #EndDateTime
group by intervaldate
) c
inner join
(
SELECT
sh.Date as Datum,
sc.Name as Name
FROM tHistory sh
INNER JOIN tSchedule sc ON (sc.ID = sh.ScheduleID)
WHERE Scheduled != 0
) p ON p.Name = c.Name
When I realized that the data was not recorded I did written down the data on paper.
To add manual data to your posted query, you can use UNION ALL and VALUES like so:
First make sure you get your 'additional data' correct on its own. Try this example:
SELECT Datum,Name,[Group],Goods,Units
FROM (
VALUES
(CAST('2015-01-01' AS DATE),'AName','A',10.32,20.76),
(CAST('2015-01-01' AS DATE),'AName','B',12.72,16.15)
) AS ExtraData(Datum,Name,[Group],Goods,Units);
I am making many assumptions here as you have not provided enough info in your question.
Anyway if that is correct, then you simply attach it to your original data with UNION ALL
SELECT Datum,Name,[Group],Goods,Units
FROM (
Select
intervaldate as Datum
,tsystem.Name as Name
,team as [Group]
,SUM(GoodUnits) As Goods
,SUM(TheoreticalUnits) As Units
from tCount inner join tsystem ON tCount.systemid = tsystem.id
where IntervalDate >= #StartDateTime AND IntervalDate <= #EndDateTime
group by intervaldate
) c
inner join
(
SELECT
sh.Date as Datum,
sc.Name as Name
FROM tHistory sh
INNER JOIN tSchedule sc ON (sc.ID = sh.ScheduleID)
WHERE Scheduled != 0
) p ON p.Name = c.Name
/* Original query ends. Now add more data */
UNION ALL
SELECT Datum,Name,[Group],Goods,Units
FROM (
VALUES
(CAST('2015-01-01' AS DATE),'AName','A',10.32,20.76),
(CAST('2015-01-01' AS DATE),'AName','B',12.72,16.15)
) AS ExtraData(Datum,Name,[Group],Goods,Units);

Display Y/N column if record found in detail table

I'm trying to create a query so that I can have a column show Y/N if a particular item was ordered for a group of orders. The item I'm looking for would be OLI.id = '538'.
So my results would be:
Order#, Customer#, FreightPaid
12345, 00112233, Y
12346, 00112233, N
I cannot figure out if I need to use a subquery or the where exists function ?
Here's my current query:
SELECT distinct
OrderID,
Accountuid as Customerno
FROM [SMILEWEB_live].[dbo].[OrderLog] OL
inner join Orderlog_item OLI on OLI.orderlogkey = OL.[key]
inner join Account A on A.uid = OL.Accountuid
where A.GroupId = 'X9955'
and OL.CreateDate >= GETDATE() - 60
I would suggest an exists clause instead of a join:
select ol.OrderID, ol.Accountuid as Customerno,
(case when exists (select 1
from Orderlog_item OLI join
Account A
on A.uid = OL.Accountuid
where OLI.orderlogkey = OL.[key] and A.GroupId = 'X9955'
)
then 1 else 0
end) as flag
from [SMILEWEB_live].[dbo].[OrderLog] OL
where OL.CreateDate >= GETDATE() - 60;
This prevents a couple of problems. First, duplicate rows which are caused when there are multiple matching rows (and select distinct add unnecessary overhead). Second, missing rows, which happen when you use inner join instead of an outer join.

Combining Multiple SQL Views ON Year & Month

I have a SQL Server database (2012 express) with many tables.
I have produced three different VIEWS based on different combinations of the underlying tables.
Each of these views consists of three columns, Year, Month & Total
The Total column in each of the 3 Views is of a different measure.
What I want to be able to do is to combine the three Totals into a single View
I have attempted this with the following script -
SELECT b.[Year], b.[Month], b.Fees AS [Billing],
f.Estimate AS [Estimate],
w.Fees AS [WIP]
FROM MonthlyBillingTotals AS b
FULL JOIN MonthlyFeeEstimates AS f
ON (b.[Year] = f.[Year] AND b.[Month] = f.[Month])
FULL JOIN MonthlyInstructionsWIP AS w
ON (b.[Year] = w.[Year] AND b.[Month] = w.[Month])
ORDER BY b.[Year], b.[Month]
Originally I tried INNER JOINS but of course unless the Year / Month combo existed in the first view (MonthlyBillingTotals) then it did not appear in the combined query. I therefore tried FULL JOINS, but the problem here is that I get some NULLS in the Year and Month columns, when they do not exist in the first view (MonthlyBillingTotals).
If the data in the three Views is as follows -
Then what I want is -
And even better (if it is possible) -
with the missing months filled in
You could try building the full list of Months/Years from your tables using a UNION subquery, and then use that to drive your joins.. Something like this:
SELECT a.[Year], a.[Month], b.Fees AS [Billing],
f.Estimate AS [Estimate],
w.Fees AS [WIP]
FROM (SELECT a.[Year], a.[Month] FROM MonthlyBillingTotals AS a
UNION
SELECT b.[Year], b.[Month] FROM MonthlyFeeEstimates AS b
UNION
SELECT c.[Year], c.[Month] FROM MonthlyInstructionsWIP AS c) AS a
LEFT OUTER JOIN MonthlyBillingTotals AS b
ON (a.[Year] = b.[Year] AND a.[Month] = b.[Month])
LEFT OUTER JOIN MonthlyFeeEstimates AS f
ON (a.[Year] = f.[Year] AND a.[Month] = f.[Month])
LEFT OUTER JOIN MonthlyInstructionsWIP AS w
ON (a.[Year] = w.[Year] AND a.[Month] = w.[Month])
ORDER BY a.[Year], a.[Month]
This is completely untested, but see if this solves your problems:
SELECT b.[Year], b.[Month], Coalesce(b.Fees, '0') AS [Billing],
Coalesce(f.Estimate,'0') AS [Estimate],
Coalesce(w.Fees,'0') AS [WIP]
FROM MonthlyBillingTotals AS b
LEFT JOIN MonthlyFeeEstimates AS f
ON (b.[Year] = f.[Year] AND b.[Month] = f.[Month])
LEFT JOIN MonthlyInstructionsWIP AS w
ON (b.[Year] = w.[Year] AND b.[Month] = w.[Month])
ORDER BY b.[Year], b.[Month]
The Coalesce function puts in a '0' value if nothing is found, and left joins should only join parts of MonthlyFeeEstimates and MonthlyInstructionsWIP when the year and month match.
You could set up a small date table with year and month and left join the views with that, and use the ISNULL(variable,0) function to replace NULL with 0. Another option instead of a date table would be to use a common table expression to generate a date range to join with. In any case I suggest you look up the date table (or numbers table), it can be a really useful tool.
Edit: added an example on how a date table can be created (for reference):
declare #year_month table (y int, m int)
;with cte as (
select cast('2000-01-01' as datetime) date_value
union all
select date_value + 1
from cte
where date_value + 1 < '2010-12-31'
)
insert #year_month (y, m)
select distinct year(date_value), month(date_value)
from cte
order by 1, 2
option (maxrecursion 0)
select * from #year_month

SQL Group By Clause and Empty Entries

I have a SQL Server 2005 query that I'm trying to assemble right now but I am having some difficulties.
I have a group by clause based on 5 columns: Project, Area, Name, User, Engineer.
Engineer is coming from another table and is a one to many relationship
WITH TempCTE
AS (
SELECT htce.HardwareProjectID AS ProjectId
,area.AreaId AS Area
,hs.NAME AS 'Status'
,COUNT(*) AS Amount
,MAX(htce.DateEdited) AS DateModified
,UserEditing AS LastModifiedName
,Engineer
,ROW_NUMBER() OVER (
PARTITION BY htce.HardwareProjectID
,area.AreaId
,hs.NAME
,htce.UserEditing ORDER BY htce.HardwareProjectID
,Engineer DESC
) AS row
FROM HardwareTestCase_Execution AS htce
INNER JOIN HardwareTestCase AS htc ON htce.HardwareTestCaseID = htc.HardwareTestCaseID
INNER JOIN HardwareTestGroup AS htg ON htc.HardwareTestGroupID = htg.HardwareTestGroupId
INNER JOIN Block AS b ON b.BlockId = htg.BlockId
INNER JOIN Area ON b.AreaId = Area.AreaId
INNER JOIN HardwareStatus AS hs ON htce.HardwareStatusID = hs.HardwareStatusId
INNER JOIN j_Project_Testcase AS jptc ON htce.HardwareProjectID = jptc.HardwareProjectId AND htce.HardwareTestCaseID = jptc.TestcaseId
WHERE (htce.DateEdited > #LastDateModified)
GROUP BY htce.HardwareProjectID
,area.AreaId
,hs.NAME
,htce.UserEditing
,jptc.Engineer
)
The gist of what I want is to be able to deal with empty Engineer columns. I don't want this column to have a blank second entry (where row=2).
What I want to do:
Group the items with "row" value of 1 & 2 together.
Select the Engineer that isn't empty.
Do not deselect engineers where there is not a matching row=2.
I've tried a series of joins to try and make things work. No luck so far.
Use j_Project_Testcase PIVOT( MAX(Engineer) for Row in ( [1], [2] ) then select ISNULL( [1],[2]) to select the Engineer value
I can give you a more robust example if you set up a SQL fiddle
Try reading this: PIVOT and UNPIVOT