Show distinct totals based on Issue & Date - tsql

I have the following results with my query:
Sample Data of the above:
declare #tbl table (DateOfService date, IssueID int, IssueName varchar(100), AssignedConsultant varchar(30), Activity varchar(100), TimeSpent float, TimeInvoiced float)
insert into #tbl (DateOfService,IssueID,IssueName,AssignedConsultant,Activity,TimeSpent,TimeInvoiced) values ('2019-12-19',10295,'Bin Issue','Doug','Activity Detail 1…',10.25,8)
insert into #tbl (DateOfService,IssueID,IssueName,AssignedConsultant,Activity,TimeSpent,TimeInvoiced) values ('2019-12-19',10295,'Bin Issue','Doug','Activity Detail 2…',10.25,8)
insert into #tbl (DateOfService,IssueID,IssueName,AssignedConsultant,Activity,TimeSpent,TimeInvoiced) values ('2020-01-24',10295,'Bin Issue','Doug','Activity Detail 3…',5.5,4)
insert into #tbl (DateOfService,IssueID,IssueName,AssignedConsultant,Activity,TimeSpent,TimeInvoiced) values ('2020-01-24',10295,'Bin Issue','Doug','Activity Detail 4…',5.5,4)
select
*
from #tbl
For reasons of confidentiality, I'm unable to share my query, however,
How would one alter these results to look like this :
As can be seen from my expected results, I only need to the total time spent and invoiced per date.
The problem I have is, this result gets used in a pivot in Excel, causing double values to reflect.
Please assist?

I assume you have some way of identifying each row, so I added and ID column to the table variable. I also left the values for the secondary rows as NULL as you were not clear about what value you wanted there. Anyways, this should work for the represented data set:
declare #tbl table (ID int,DateOfService date, IssueID int, IssueName varchar(100), AssignedConsultant varchar(30), Activity varchar(100), TimeSpent float, TimeInvoiced float)
insert into #tbl (ID,DateOfService,IssueID,IssueName,AssignedConsultant,Activity,TimeSpent,TimeInvoiced) values (1,'2019-12-19',10295,'Bin Issue','Doug','Activity Detail 1…',10.25,8)
insert into #tbl (ID,DateOfService,IssueID,IssueName,AssignedConsultant,Activity,TimeSpent,TimeInvoiced) values (2,'2019-12-19',10295,'Bin Issue','Doug','Activity Detail 2…',10.25,8)
insert into #tbl (ID,DateOfService,IssueID,IssueName,AssignedConsultant,Activity,TimeSpent,TimeInvoiced) values (3,'2020-01-24',10295,'Bin Issue','Doug','Activity Detail 3…',5.5,4)
insert into #tbl (ID,DateOfService,IssueID,IssueName,AssignedConsultant,Activity,TimeSpent,TimeInvoiced) values (4,'2020-01-24',10295,'Bin Issue','Doug','Activity Detail 4…',5.5,4)
;WITH CTE AS (
SELECT MIN(ID) ID, DateOfService
FROM #tbl
GROUP BY DateOfService
)
SELECT T1.DateOfService,
IssueID,
IssueName,
AssignedConsultant,
Activity,
CASE WHEN T2.ID IS NULL THEN NULL ELSE T1.TimeSpent END TimeSpent,
CASE WHEN T2.ID IS NULL THEN NULL ELSE T1.TimeInvoiced END TimeInvoiced
FROM #tbl T1
LEFT JOIN CTE T2 on T1.ID = T2.ID

I didn't think this would work, but it looks like it does for these results.
Herewith what I've come up with (not sure if it's technically right), but it works for me:
declare #tbl table (DateOfService date, IssueID int, IssueName varchar(100), AssignedConsultant varchar(30), Activity varchar(100), TimeSpent float, TimeInvoiced float)
insert into #tbl (DateOfService,IssueID,IssueName,AssignedConsultant,Activity,TimeSpent,TimeInvoiced) values ('2019-12-19',10295,'Bin Issue','Doug','Activity Detail 1…',10.25,8)
insert into #tbl (DateOfService,IssueID,IssueName,AssignedConsultant,Activity,TimeSpent,TimeInvoiced) values ('2019-12-19',10295,'Bin Issue','Doug','Activity Detail 2…',10.25,8)
insert into #tbl (DateOfService,IssueID,IssueName,AssignedConsultant,Activity,TimeSpent,TimeInvoiced) values ('2020-01-24',10295,'Bin Issue','Doug','Activity Detail 3…',5.5,4)
insert into #tbl (DateOfService,IssueID,IssueName,AssignedConsultant,Activity,TimeSpent,TimeInvoiced) values ('2020-01-24',10295,'Bin Issue','Doug','Activity Detail 4…',5.5,4)
select
DateOfService
, IssueID
, IssueName
, AssignedConsultant
, Activity
, case when lag(TimeSpent) over (order by IssueName) = TimeSpent then 0 else TimeSpent end TimeSpent
, case when lag(TimeInvoiced) over (order by IssueName) = TimeInvoiced then 0 else TimeInvoiced end TimeInvoiced
from #tbl
See the results in db<>fiddle

Related

Delete duplicate rows with different values in columns

I didn't find my case on the Internet. Tell me how i can delete duplicates if the values are in different columns.
I have a table with a lot of values, for example:
|Id1|Id2|
|89417980|89417978|
|89417980|89417979|
|89417978|89417980|
|89417979|89417980|
I need to exclude duplicates and leave in the answer only:
|Id1|Id2|
|89417980|89417978|
|89417980|89417979|
min/max does not work here, as the values may be different.
I tried to union/join tables on a table/exclude results with temporary tables, but in the end I come to the beginning.
Assuming id1 and id2 are primary keys columns you could try this
DECLARE #tbl table (id1 int, id2 int )
INSERT INTO #tbl
SELECT 89417980, 89417978
UNION SELECT 89417980, 89417979
UNION SELECT 89417978, 89417980
UNION SELECT 89417979, 89417980
SELECT * FROM #tbl
;WITH CTE AS (--Get comparable value as "cs"
SELECT
IIF(id1 > id2, CHECKSUM(id1, id2), CHECKSUM(id2,id1)) as cs
, id1
, id2
, ROW_NUMBER() OVER (order by id1, id2) as rn
FROM #tbl
)
, CTE2 AS ( --Get rows to keep
SELECT MAX (rn) as rn
FROM CTE
GROUP BY cs
HAVING COUNT(*) > 1
)
DELETE tbl -- Delete all except the rows to keep
FROM #tbl tbl
WHERE NOT EXISTS(SELECT 1
FROM CTE2
JOIN CTE ON CTE.rn = CTE2.rn
WHERE CTE.id1 = tbl.id1
AND CTE.id2 = tbl.id2
)
SELECT * FROM #tbl

sql compare columns to get result

I have the following issue. I have products with 3 different states. Parent, Child and products which are orphans. I am setting Parents as 1, Children as 2 and Orphans as 0. I am struggling to get the Orphan to set to 0. I realise that counting the amount of Parent PLU's is where I am going wrong but I do not know how to resolve this issue. Any help would be appreciated. (As you maybe able to tell, I am a noob and constructive criticism would be appreciated)
Kind Regards,
Jason.
Picture of results from query
declare #OrderID int = 1635
declare #Store char(3) = '001'
declare #SortedBy smallint = 2
DECLARE #tbl TABLE (DetailID int, OrderID int, PLU nvarchar(35), ParentPLU nvarchar(35))
INSERT INTO #tbl (DetailID, OrderID, PLU, ParentPLU)
SELECT DetailID, OrderDetails.OrderID, OrderDetails.PLU, OrderDetails.ParentPLU
FROM OrderDetails
INNER JOIN PLU
ON PLU.PLU = OrderDetails.PLU
WHERE OrderDetails.OrderID = #OrderID
AND OrderDetails.OrderStore = #Store
SELECT DetailID, OrderID, PLU, ParentPLU,
CASE WHEN ( SELECT COUNT(DISTINCT ParentPLU)
FROM #tbl
WHERE ParentPLU IN (SELECT PLU FROM #tbl)
) > 0 AND ParentPLU = '' THEN 1
WHEN ( SELECT COUNT(DISTINCT ParentPLU)
FROM #tbl
WHERE ParentPLU IN (SELECT PLU FROM #tbl)
) > 0 THEN 2
ELSE
0
END AS ParentChild,
ROW_NUMBER() OVER (ORDER BY
CASE WHEN #SortedBy = 1 THEN OrderID END ASC,
CASE WHEN #SortedBy = 2 THEN DetailID END ASC
) AS ID
FROM #tbl
You can use coalesce to get your desired result. First subquery checks for parent state, second for children. If both are null, then it is orphan
select
DetailID, OrderID, PLU, ParentPLU
, coalesce((
select
distinct 1
from
#tbl b
where
a.PLU = b.ParentPlu
)
, (
select
distinct 2
from
#tbl b
where
b.PLU = a.ParentPlu
), 0)
from
#tbl a

Is there a shortcut to deleting all in one table not in another?

Are there any shortcuts for deleting everything in one table that does not exist in the second?
I know I can do this:
DECLARE #Table1 TABLE (ID INT)
DECLARE #Table2 TABLE (ID INT)
INSERT INTO #Table1 VALUES (1),(2),(3),(4)
INSERT INTO #Table2 VALUES (3),(4)
DELETE t1
FROM #Table1 t1
WHERE NOT EXISTS (SELECT 1 FROM #Table2 t2 WHERE t2.ID = t1.ID)
SELECT * FROM #Table1
However, I have over 600 columns, so you can see why I might be reluctant to go that route if there's another way. What I WANT to do would look like this:
DECLARE #Table1 TABLE (ID INT)
DECLARE #Table2 TABLE (ID INT)
INSERT INTO #Table1 VALUES (1),(2),(3),(4)
INSERT INTO #Table2 VALUES (3),(4)
DELETE #Table1
EXCEPT SELECT * FROM #Table2
That EXCEPT has been very handy in dealing with this project I'm working on, but I guess it's limited.
Please use this:
DELETE FROM #Table1 WHERE BINARY_CHECKSUM(*) NOT IN(SELECT BINARY_CHECKSUM(*) FROM #Table2);
But be carefull, if your table contains float data types. In very rare cases wrong checksum may be calculated. But, these cases are rare and random, no problems will remain after second delete iteration.
Sure:
DELETE t1
FROM #Table1 t1
LEFT JOIN #Table2 t2 ON t2.ID = t1.ID
WHERE t2.ID IS NULL
My first answer was about the case, when t1 and t2 tables are the same, and joined corressponding cols, when deciding deletion.
Ok, now about the other situation: your #table1 column [ID] can by joined with any unknown #table2 column. You can solve 600+ cols problem using XML:
DELETE FROM #Table1 WHERE CONVERT(NVARCHAR, [ID]) NOT IN
(
SELECT
[col].[value]('(.)[1]', 'NVARCHAR(MAX)')
FROM
(
SELECT [xml] = (CONVERT(XML, (SELECT * FROM #Table2 FOR XML PATH('t2'))))
) AS [t2]
CROSS APPLY [t2].[xml].[nodes]('t2/*') AS [tab]([col])
);

Remove Duplicates

I have a table like below:
SuppID AreaID SuppNo SupName SupPrice
------------------------------------------------
1 3 526 ANC 100
1 3 985 JTT 200
3 4 100 HIK 300
In the above table, for same SuppID(1) and same AreaID(3), different SuppNo are there (526 & 985) in two different rows.
In this scenario , I'd like to make those two rows into a single row with SuppNo field as blank.
Also my output result should display rows with all the columns.
Any Help?
This should get you started:
DECLARE #TABLE TABLE (SuppID INT, AreaID INT, SuppNo VARCHAR(5), SupName VARCHAR(5), SupPrice INT)
INSERT INTO #TABLE
SELECT 1,3,'526','ANC',100 UNION
SELECT 1,3,'985','JTT',200 UNION
SELECT 3,4,'100','HIK',300
-- select data before updates
SELECT * FROM #TABLE
-- add a row count by AreaID/SuppID
;WITH T1 AS
(
SELECT *
,SUM(1) OVER(PARTITION BY AREAID,SUPPID) AS ROWCNT
FROM #TABLE
)
-- set the SuppNo blank on rows that have more than 1 match
UPDATE T1 SET SuppNo='' WHERE ROWCNT>1
-- add a row # by AreaID/SuppID
;WITH T2 AS
(
SELECT *
,ROW_NUMBER() OVER(PARTITION BY AREAID,SUPPID ORDER BY AREAID,SUPPID) AS ROWID
FROM #TABLE
)
-- delete duplicate rows
DELETE
FROM T2
WHERE ROWID>1
-- select data after updates
SELECT * FROM #TABLE

T-SQL Average of Table Subset

I have a table (in SQL Server 2005) of daily weather data for a single location which includes these columns:
LogDate DATETIME
HighTemp INT
Temp6MonthHighAverage INT
LogDate and HighTemp have data. HighTemp6MonthAverage will be populated with, as the name suggests, the average high temperature for the 6 months ending in LogDate.
There are similar requirements for LowTemp, as well as humidity and several other items, for data spanning decades.
I find myself thinking in circles. Can I derive this average for each row in an UPDATE statement using set operations, or do I need to implement a solution with cursors? I will appreciate any suggestions.
-- select
select HighTemp, LogDate,(select AVG(HighTemp)
from tbl where
DATEDIFF(MONTH, LogDate, t1.LogDate) between 0 and 6)
from tbl t1
-- update
update t1 set Temp6MonthHighAverage = (select AVG(HighTemp)
from tbl where
DATEDIFF(MONTH, LogDate, t1.LogDate) between 0 and 6)
from tbl t1
You can certainly do this with a simple UPDATE:
UPDATE table SET Temp6MonthHighAverage =
(SELECT AVG(HighTemp) FROM table t2 WHERE
t2.LogDate <= table.LogDate
AND t2.LogDate > DATEADD(m, -6, table.LogDate)
)
To avoid re-calculating constantly (since the past will not change), just add a WHERE Temp6MonthHighAverage IS NULL at the end and the same UPDATE can be run as needed to fill in the gaps as new dates are added.
Have a look at something like this
DECLARE #Table TABLE(
LogDate DATETIME,
HighTemp INT,
Temp6MonthHighAverage INT
)
INSERT INTO #Table SELECT '01 Jan 2000', 15, NULL
INSERT INTO #Table SELECT '01 May 2000', 14, NULL
INSERT INTO #Table SELECT '01 Jun 2000', 13, NULL
INSERT INTO #Table SELECT '01 Jul 2000', 12, NULL
INSERT INTO #Table SELECT '01 Dec 2000', 17, NULL
SELECT *
FROM #Table
;WITH DistinctDates AS (
SELECT DATEADD(month,-6,LogDate) StartDate,
LogDate EndDate,
HighTemp
FROM #Table
)
, Aggregates AS (
SELECT dd.EndDate LogDate,
dd.HighTemp,
MAX(t.HighTemp) Temp6MonthHighAverage
FROM DistinctDates dd LEFT JOIN
#Table t ON t.LogDate BETWEEN dd.StartDate AND dd.EndDate
GROUP BY dd.EndDate,
dd.HighTemp
)
UPDATE #Table
SET Temp6MonthHighAverage = a.Temp6MonthHighAverage
FROM #Table t INNER JOIN
Aggregates a ON t.LogDate = a.LogDate
SELECT *
FROM #Table