group by clause - sql

i have a table called table1 and it has following columns.
suppose there are records like localamount is 20,000, 30000,50000, 100000 then as per my condition i have to delete records from this table according to the group by set of site id, till id, transid,shift id where localamount exceeds 10,000... the rest of the records can be available?
my aim is to delete rows from this table where local amount is exceeds 10,0000 according to site id, till id, transid,shift id
SiteId varchar(10),
TillId tinyint,
ShiftId int,
TransId int,
TranDate datetime,
SettlementType varchar(5),
CreditCardNumber varchar(25),
ProductTypeCode varchar(10),
NewProductTypeCode varchar(10),
TransactionType int,
ForeignAmount money,
LocalAmount money,
ProductCode varchar(10)

Im not sure I understand what you are saying, but couldn't you do this without a group by?
delete from table1 where LocalAmount > 10,0000[sic] and SiteId = whatever and TillId = whatever...
obviously take the [sic] out...

Assuming you want to delete the whole group where the sum is > 10000
;with cte as
(
select sum(localamount) over
(partition by siteid, tillid, transid,shiftid) as l,
* from table1
)
delete from cte where l>10000

Related

Get SQL Distinct Row Without NULL Values

I'm trying to get a distinct row using SQL from set of records that have matching key/id value, but NULLs in different columns. Hard to explain so please see screenshot. Any ideas?
create temporary table my_table (
id varchar(30), segmentdate1 date, converted1 varchar(10), segmentdate2 date, converted2 varchar(10)
);
insert into my_table (
id, segmentdate1, converted1, segmentdate2, converted2
)
values
('Michael','9/15/2020','No',NULL,NULL),
('Michael',NULL,NULL,'7/1/2019','Yes')
;
You seem to want aggregation:
select id, max(segmentdate1) as segmentdate1, max(converted1) as converted1,
max(segmentdate2) as segmentdate2, max(converted2) as converted2
from t
group by id;
Note: I made up names for the columns so they are unique.
This is probably a result set created from another query. That query probably has the wrong group by keys. You should probably fix that query.
declare #my_table table (
id varchar(30), segmentdate1 date, converted1 varchar(10), segmentdate2 date, converted2 varchar(10)
);
insert into #my_table (
id, segmentdate1, converted1, segmentdate2, converted2
)
values
('Michael','9/15/2020','No',NULL,NULL),
('Michael',NULL,NULL,'7/1/2019','Yes')
;
select id,max(isnull(segmentdate1,'1200-01-01')) segmentdate2
,max(isnull(converted1,'')) converted1, max(isnull(segmentdate2,'1200-01-01')) segmentdate2
,max(isnull(converted2,'')) converted2
from #my_table
group by id

Preparing Rules Based List for Promotions

I am trying to put together a promotions list based on a set of rules
In table #productdetail I need to pick up items that have available =1 or available =2 and expected <=08052019 and not_sellable =0
From #product table I need to join id with pid in #productdetail and coalesce (vendor_id to get the vendor_id
Using the vendor_id that I have got from the step above i need to get the vendorname from #vendor table..
From the #Asin table I need to select the latest lastconfirmedasin from the list of items selected in step 1 and also ensure that I should not pick up data from rows where disable =1
From the #pageviews table I need to get the number of pageviews perday for every item based on the lastconfirmedasin for the list of items selected in step 1
Here for every item if I have datetype =day and also datetype =month then I need to select data from datetype =day and select sum(pageviews)/count of days to get the sum of pageviews per day
Also if I have only datetype =month then I need to select (sum(pageviews)(count of rows that have month)/30
Then in the promo table I need to select the average promo% got for the items selected in step 1..The average promo% is calculated as avg((pre_promo_price-promo_price)/promo_price*100))...This will be calculated at the vendor level...So if the vendor has 3 items then the average promo% is calculated as avg([avg((pre_promo_price-promo_price)/promo_price*100)
Then the cost is taken based on if in the table #promo has the date in between or included in promo_start and promo_end (for example today's date being 08/16/2019 is included then the pre promo cost is to taken as the cost for that item otherwise the cost from #product_detail table should be taken
Then I am calculating the priority of the items by vendor(meaning within each vendor ) prioritizing the items based on the power(calculated as pageviewsperday*price)-Higher value of an item within a vendor gets the first priority
The tables:
create table #productdetail
(
itemid int,
available int,
expected date,
isnotsellable int,
pid int,
vendor_id varchar(50),
cost float,
price float)
insert into #productdetail values
('123','1',NULL,'1','1','201','180','200'),
('125','2','08/05/2019','0','1','NULL','40','60'),
('127','1',NULL,'0','1','201','60','80'),
('129','2',NULL,'0','2','203','80','100'),
('131','1',NULL,'0','2','203','70','90'),
('133','1',NULL,'1','2','203','90','110'),
('135','1',NULL,'0','7','206','110','130'),
('137','1',NULL,'0','8','207','120','140'),
('139','1',NULL,'0','8','207','30','50'),
('141','1',NULL,'0','8','207','40','60'),
('143','1',NULL,'0','11','210','60','80'),
('145','1',NULL,'0','11','210','70','90'),
('147','1',NULL,'1','11','210','50','70'),
('149','1',NULL,'0','11','210','20','40'),
('151','1',NULL,'0','15','211','30','50'),
('153','1',NULL,'0','16','NULL','40','60'),
('155','2','08/29/2019','1','15','211','60','80'),
('157','2','08/04/2019','1','18','216','30','50'),
('159','2','08/06/2019','0','19','217','20','40'),
('161','2','08/03/2019','0','20','218','60','80'),
('163','2','08/15/2019','0','21','NULL','90','110')
create table #product
(id int,
vendor_id varchar(50)
)
insert into #product values
('1','201'),
('1','201'),
('1','201'),
('2','203'),
('2','203'),
('2','203'),
('7','NULL'),
('8','207'),
('8','207'),
('8','207'),
('11','210'),
('11','210'),
('11','210'),
('11','210'),
('15','211'),
('15','211'),
('15','211'),
('16','206'),
('18','216'),
('19','NULL'),
('20','218'),
('21','219')
create table #vendor
(vendor_id varchar(50),
vendorname varchar(50)
)
insert into #vendor values
('201','cola'),
('203','foam'),
('207','fill'),
('210','falon'),
('211','chiran'),
('216','Hummer'),
('218','sulps'),
('219','culp'),
('217','jko'),
('206','JINCO')
create table #asin
(disable int,
item_id int,
lastconfirmed datetime2,
lastconfirmedasin varchar(50)
)
insert into #asin values
('0','123','12/19/18 10:19 PM','iopyu'),
('1','123','12/19/16 10:19 PM','hjyug'),
('1','125','5/19/19 10:19 PM','uirty'),
('0','125','12/19/16 10:19 PM','1yuio'),
('0','127','2/19/19 10:19 PM','klbnm'),
('1','127','12/19/18 10:19 PM','lopgh'),
('0','127','12/19/16 10:19 PM','nmbh'),
('0','129','11/19/16 10:19 PM','jklh'),
('0','131','11/19/19 10:19 PM','werat'),
('1','133','6/19/19 10:19 PM','vbnwe'),
('0','133','1/19/19 10:19 PM','mnwer'),
('0','133','11/19/17 10:19 PM','sdert'),
('0','135','6/19/19 10:19 PM','vbsdx'),
('0','137','6/19/17 10:19 PM','bnxct')
create table #pageviews
(startdate date,
lastconfirmedasin varchar(50),
noofpageviews int,
datetype varchar(20))
insert into #pageviews values
('05/08/2017','hjyug','102','day'),
('09/05/2017','hjyug','201','day'),
('10/05/2019','hjyug','1002','day'),
('09/05/2018','iopyu','345','month'),
('10/06/2018','iopyu','545','month'),
('06/05/2019','1yuio','300','day'),
('06/06/2019','1yuio','200','day'),
('09/04/2019','uirty','150','day'),
('11/4/2019','uirty','200','day'),
('12/4/2019','nmbh','300','day'),
('04/15/2019','lopgh','400','day'),
('04/15/2019','klbnm','500','day'),
('04/16/2019','klbnm','1000','day'),
('04/15/2019','jklh','600','day'),
('04/15/2019','werat','700','day'),
('04/15/2019','sdert','800','day'),
('04/15/2019','mnwer','900','day'),
('04/15/2019','vbnwe','1000','day'),
('04/15/2019','vbsdx','1100','day'),
('04/25/2019','vbsdx','3000','day'),
('04/15/2019','bnxct','1200','month'),
('05/31/2019','bnxct','2200','month'),
('04/16/2019','bnxct','90','day'),
('04/17/2019','bnxct','100','day'),
('04/18/2019','bnxct','120','day')
create table #promo
(itemid int,
promo_cost float,
pre_promo_cost float,
promo_start varchar(50),
promo_end varchar(50))
insert into #promo values
('123','214.7','220','10/08/2019','22/08/2019'),
('123','225','230','01/02/2018','15/02/2018'),
('125','400','430','12/08/2019','19/08/2019'),
('125','380','390','15/02/2019','30/02/2019'),
('127','120','140','15/03/2019','30/03/2019'),
('129','80','100','15/04/2019','30/04/2019'),
('129','110','120','01/04/2019','10/04/2019'),
('131','80','100','01/02/2019','15/02/2019'),
('131','110','120','10/01/2019','15/01/2019'),
('133','230','420','10/01/2019','15/01/2019'),
('135','250','440','10/01/2019','15/01/2019'),
('137','270','460','10/01/2019','15/01/2019'),
('139','290','480','10/01/2019','15/01/2019'),
('141','310','500','10/01/2019','15/01/2019'),
('143','330','520','10/01/2019','15/01/2019'),
('145','350','540','10/08/2019','22/08/2019')
create table #output
(itemid int,
available int,
expected date,
isnotsellable int,
pid int,
vendor_id varchar(50),
vendorname varchar(50),
lastconfirmedasin varchar(50),
pageviewsperday int,
promoavg float,
cost float,
price float,
[power] int,
[priority] int)
insert into #output values
('151','1',NULL,'0','15','211','chiran','','0','0','30','50','0','1'),
('127','1',NULL,'0','1','201','cola','klbnm','750','6.3','60','80','60000','1'),
('125','2','08/05/2019','0','1','201','cola','','0','0','430','60','0','2'),
('143','1',NULL,'0','11','210','falon','','0','0','60','80','0','1'),
('145','1',NULL,'0','11','210','falon','','0','0','540','90','0','2'),
('149','1',NULL,'0','11','210','falon','','0','0','20','40','0','3'),
('137','1',NULL,'0','8','207','fill','bnxct','103','65.73','120','140','14420','1'),
('139','1',NULL,'0','8','207','fill','','0','0','30','50','0','2'),
('141','1',NULL,'0','8','207','fill','','0','0','40','60','0','3'),
('131','1',NULL,'0','2','203','foam','werat','700','30.16','70','90','63000','1'),
('135','1',NULL,'0','7','206','JINCO','vbsdx','2050','76','110','130','266500','1'),
('153','1',NULL,'0','16','206','JINCO','','0','0','40','60','0','2'),
('161','2','08/03/2019','0','20','218','sulps','','0','0','60','80','0','1')
Code tried:
; WITH firstsel AS (
SELECT itemid, available, expected, isnotsellable, pid, vendor_id
FROM #productdetail
WHERE available = 1
AND isnotsellable = 0
UNION ALL
SELECT itemid, available, expected, isnotsellable, pid, vendor_id
FROM #productdetail
WHERE available = 2
AND isnotsellable = 0
AND expected <= '20190805'
), addvendorid AS (
SELECT fs.itemid, fs.available, fs.expected, fs.pid, fs.isnotsellable,
coalesce(fs.vendor_id, p.vendor_id) AS vendor_id
FROM firstsel fs
JOIN #product p ON fs.pid = p.id
), asinnumbered AS (
SELECT item_id, lastconfirmedasin, row_number() OVER (PARTITION BY item_id ORDER BY lastconfirmedasin DESC) AS rowno
FROM #asin
)
SELECT av.itemid, av.available, av.expected, av.isnotsellable, av.pid,
av.vendor_id, v.vendorname, an.lastconfirmedasin,
isnull(pv.pageviews, 0) AS pageviews, isnull(p.promoavg, 0) AS promoavg
FROM addvendorid av
JOIN #vendor v ON av.vendor_id = v.vendor_id
LEFT JOIN (asinnumbered an
JOIN (SELECT lastconfirmedasin, SUM(pageviews) AS pageviews
FROM #pageviews
GROUP BY lastconfirmedasin) AS pv ON an.lastconfirmedasin = pv.lastconfirmedasin)
ON an.item_id = av.itemid
AND an.rowno = 1
LEFT JOIN (SELECT itemid, avg((pre_promo_price-promo_price)/promo_price*100) AS promoavg
FROM #promo
GROUP BY itemid) AS p ON p.itemid = av.itemid
ORDER BY av.itemid

Delete duplicate rows with soundex?

I have two tables, one has foreign keys to the other. I want to delete duplicates from Table 1 at the same time updating the keys on Table 2. I.e count the duplicates on Table 1 keep 1 key from the duplicates and query the rest of the duplicate records on Table 2 replacing them with the key I'm keeping from Table 1. Soundex would be the best option because not all the names are spelled right in Table 1. I have the basic algorithm but not sure how to do it. Help?
So far this is what I have:
declare #Duplicate int
declare #OriginalKey int
create table #tempTable1
(
CourseID int, <--- The Key I want to keep or delete
SchoolID int,
CourseName nvarchar(100),
Category nvarchar(100),
IsReqThisYear bit,
yearrequired int
);
create table #tempTable2
(
CertID int,
UserID int,
CourseID int, <---- Must stay updated with Table 1
SchoolID int,
StartDateOfCourse datetime,
EndDateOfCourse datetime,
Type nvarchar(100),
HrsOfClass float,
Category nvarchar(100),
Cost money,
PassFail varchar(20),
Comments nvarchar(1024),
ExpiryDate datetime,
Instructor nvarchar(200),
Level nchar(10)
)
--Deletes records from Table 1 not used in Table 2--
delete from Table1
where CourseID not in (select CourseID from Table2 where CourseID is not null)
insert into #tempTable1(CourseID, SchoolID, CourseName, Category, IsReqThisYear, yearrequired)
select CourseID, SchoolID, CourseName, Category, IsReqThisYear, yearrequired from Table1
insert into #tempTable2(CertID, UserID, CourseID, SchoolID, StartDateOfCourse, EndDateOfCourse, Type, HrsOfClass,Category, Cost, PassFail, Comments, ExpiryDate, Instructor, Level)
select CertID, UserID, CourseID, SchoolID, StartDateOfCourse, EndDateOfCourse, Type, HrsOfClass,Category, Cost, PassFail, Comments, ExpiryDate, Instructor, Level from Table2
select cour.CourseName, Count(cour.CourseName) cnt from Table1 as cour
join #tempTable1 as temp on cour.CourseID = temp.CourseID
where SOUNDEX(temp.CourseName) = SOUNDEX(cour.CourseName) <---
The last part does not exactly work, gives me an error
Error: Column 'Table1.CourseName' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
UPDATE: Some of the names in CourseName have numbers in them too. Like some are in romans and numeral format. Need to find those too but Soundex ignores numbers.

SQL query Optimization help

I have the the following SQL query
Declare #tempcalctbl Table
(
ItemId varchar(50),
ItemLocation varchar(50),
ItemNo varchar(50),
Width real,
Unit varchar(50),
date datetime
)
Insert Into #tempcalctbl
Select distinct SubId,ItemLocation,ItemNo,
(ABS((Select width From #temptbl a Where ItemProcess ='P1'and a.ItemId = c.ItemId
and a.ItemNo = c.ItemNo and a.ItemLocation = c.ItemLocation)
-(Select width From #temptbl b Where ItemProcess ='P2' and b.ItemId = c.ItemId
and b.ItemNo = c.ItemNo and b.ItemLocation = c.ItemLocation))) * 1000,
Unit,date
From #temptbl c
Group by ItemId,ItemLocation,ItemNo,Unit,date
I was wondering how to optimize this query.
The idea is to find out the different in width (p1's item - p2's item) between ItemProcess 'P1' and 'P2' according to the same ItemID, same ItemNo and same ItemLocation.
I have around 75000 and it took more then 25 minute to get the width differences for all the ItemId.
I tried to use Group by for the width different calculation but it would return multiple row instead of just a value which then would return error. By the way I am use MS SQL server 2008 and #tempcalctbl is a table that I declared in a store procedure.
Does the following help?
INSERT INTO #tempcalctbl
SELECT P1.SubId ,
P1.ItemLocation ,
P1.ItemNo ,
ABS(P1.Width - P2.Width) * 1000 AS Width ,
P1.Unit ,
P1.date
FROM #temptbl AS P1
INNER JOIN #temptbl AS P2 ON P1.ItemId = P2.ItemId
AND P1.ItemNo = P2.ItemNo
AND P1.ItemLocation = P2.ItemLocation
WHERE P1.ItemProcess = 'P1'
AND P2.ItemProcess = 'P2'
EDIT
To make use of indexes, you will need to change your table variable to a temporary table
CREATE TABLE #temptbl
(
ItemId varchar(50),
ItemLocation varchar(50),
ItemNo varchar(50),
Width real,
Unit varchar(50),
date DATETIME,
ItemProcess INT,
SubId INT
)
CREATE NONCLUSTERED INDEX Index01 ON #temptbl
(
ItemProcess ASC,
ItemId ASC,
ItemLocation ASC,
ItemNo ASC
)
INCLUDE ( SubId,Width,Unit,date)
GO
That should speed you up a little.
John Petrak's answer is the best query for this case.
If the speed is still now acceptable, maybe you can store #temptbl at a temporary real table, and create the related index on those four columns.

SQL Select Best practice

The following works, I'm just wondering if this is the correct approach to finding the latest value for each audit field.
USE tempdb
CREATE Table Tbl(
TblID Int,
AuditFieldID Int,
AuditValue Int,
AuditDate Date
)
GO
INSERT INTO Tbl(TblID,AuditFieldID,AuditValue,AuditDate) VALUES(1,10,101,'1/1/2001')
INSERT INTO Tbl(TblID,AuditFieldID,AuditValue,AuditDate) VALUES(2,10,102,'1/1/2002')
INSERT INTO Tbl(TblID,AuditFieldID,AuditValue,AuditDate) VALUES(3,20,201,'1/1/2001')
INSERT INTO Tbl(TblID,AuditFieldID,AuditValue,AuditDate) VALUES(4,20,202,'1/1/2009')
SELECT AuditFieldID,AuditValue,AuditDate
FROM Tbl A
WHERE TblID=
(SELECT TOP 1 TblID
FROM Tbl
WHERE AuditFieldID=A.AuditFieldID
ORDER BY AuditDate DESC
)
Aggregate/ranking to get key and latest date, join back to get value.
This assumes SQL Server 2005+
DECLARE #tbl Table (
TblID Int,
AuditFieldID Int,
AuditValue Int,
AuditDate Date
)
INSERT INTO #tbl(TblID,AuditFieldID,AuditValue,AuditDate) VALUES(1,10,101,'1/1/2001')
INSERT INTO #tbl(TblID,AuditFieldID,AuditValue,AuditDate) VALUES(2,10,102,'1/1/2002')
INSERT INTO #tbl(TblID,AuditFieldID,AuditValue,AuditDate) VALUES(3,20,201,'1/1/2001')
INSERT INTO #tbl(TblID,AuditFieldID,AuditValue,AuditDate) VALUES(4,20,202,'1/1/2009')
;WITH cLatest AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY AuditFieldID ORDER BY AuditDate DESC) AS Ranking,
AuditFieldID, AuditDate
FROM
#tbl
)
SELECT
A.AuditFieldID, A.AuditValue, A.AuditDate
FROM
#tbl A
JOIN
cLatest C ON A.AuditFieldID = C.AuditFieldID AND A.AuditDate = C.AuditDate
WHERE
C.Ranking = 1
Simpler:
SELECT top 1 AuditFieldID,AuditValue,AuditDate
FROM Tbl
order by AuditDate DES
There are various methods for doing this. Different methods perform differently. I encourage you to look at this blog which explains the various methods.
Including an Aggregated Column's Related Values
you don't need the where statement as you are already selecting from tbl A AND selecting on the same field.