How to add a flag column based on column values and COUNT() of records partitioned by customer in SQL Server - sql

My SQL Server table looks like this:
DayNo. Customer AgentsInvolved CallID DesiredFlag
-------------------------------------------------------
0 AAA 1 1858 0
0 AAA 3 1859 0
2 AAA 1 1860 0
0 BBB 2 1862 0
0 CCC 1 1863 1
0 DDD 3 1864 0
9 DDD 1 1865 0
9 DDD 4 1866 0
How do I add a new column to say;
WHEN (DayNo. = 0, and AgentsInvolved = 1) AND COUNT(callID) = 1 (grouped by customer)
THEN 1
ELSE 0
The column values I understand can be wrapped into a case statement but not sure how to add the condition for the COUNT(CallID). See the DesiredFlag column to see the result I'm trying to achieve.
Any help would be great.

I would use NOT EXISTS :
SELECT t.*,
(CASE WHEN NOT EXISTS (SELECT 1
FROM table t1
WHERE t1.Customer = t.Customer AND t1.CallID <> t.CallID
) AND t.DayNo = 0 AND t.AgentsInvolved = 1
THEN 1
ELSE 0
END) AS DesiredFlag
FROM table t;

with SAMPLE DATA:
declare #T Table (DayNo int,Customer varchar(10),AgentsInvolved int,CallID int)
insert into #T values
(0,'AAA',1,1858),
(0,'AAA',3,1859),
(2,'AAA',1,1860),
(0,'BBB',2,1862),
(0,'CCC',1,1863),
(0,'DDD',3,1864),
(9,'DDD',1,1865),
(9,'DDD',4,1866)
you can get your result (as i understand correctly) by:
;with summation as
(
select Customer, count(1) as qty
from #T
group by Customer
)
select
T.*,
coalesce(F.flag, 0) as flag
from
#T T
inner join summation s on s.Customer = T.Customer
outer apply (select 1 as flag where DayNo = 0 and AgentsInvolved = 1 and qty = 1) F
RESULTS:
DayNo Customer AgentsInvolved CallID flag
----------- ---------- -------------- ----------- -----------
0 AAA 1 1858 0
0 AAA 3 1859 0
2 AAA 1 1860 0
0 BBB 2 1862 0
0 CCC 1 1863 1
0 DDD 3 1864 0
9 DDD 1 1865 0
9 DDD 4 1866 0

Related

How to write sql query to get this result

I had two tables as below:
request_id
update_from_id
sw_ref_number
raised_by_user_id
raised_date
1
0
1
3
2019-08-29 15:08:16.000
id
request_id
input_id
value
is_deleted
21
1
1
00001
0
22
1
2
3
0
75
2
1
00002
0
76
2
2
0
My query is:
select req.request_id,
req.sw_ref_number,
reqDet.[value] ,
reqDet.input_id
FROM SOF.tblSOFRequest req
left join SOF.tblSOFRequestDetails reqDet
on req.request_id = reqDet.request_id
where reqDet.input_id = 1
or reqDet.input_id = 2
And after that my result is:
request_id
sw_ref_number
value
input_id
1
1
00001
1
1
1
3
2
2
2
00002
1
2
2
2
I want a result as:
request_id
sw_ref_number
epi_db_no
manuf_no
1
1
00001
3
2
2
00002
Here input_id = 1 means epi_db_no and input_id = 2 means manuf_no.
How can I get this?
Thanks
You can do it using self-join like the following query.
SELECT req.request_id
,req.sw_ref_number
,reqDet.[value] AS epi_db_no
,reqDet2.[value] AS manuf_no
FROM SOF.tblSOFRequest req
LEFT JOIN SOF.tblSOFRequestDetails reqDet ON req.request_id = reqDet.request_id
LEFT JOIN SOF.tblSOFRequestDetails reqDet2 ON reqDet.request_id = reqDet2.request_id
AND reqDet2.input_id = 2
WHERE reqDet.input_id = 1
This seems like a simple pivot. I use conditional aggregation here:
SELECT req.request_id,
req.sw_ref_number,
MAX(CASE reqDet.input_id WHEN 1 THEN reqDet.[value] END) AS epi_db_no,
MAX(CASE reqDet.input_id WHEN 2 THEN reqDet.[value] END) AS manuf_no
FROM SOF.tblSOFRequest req
JOIN SOF.tblSOFRequestDetails reqDet ON req.request_id = reqDet.request_id
WHERE reqDet.input_id IN (1,2)
GROUP BY req.request_id,
req.sw_ref_number;

How to select a Algokey when [ UserSelect] column has any of row value is 1 otherwise switch to[ SytemSelect]column haivng row value is 1

I have a table with Scenario,Product,AlgoKey,User Select,System Select columns, I have to select the algo key for each scenario, The first priority goes to user selected otherwise system selected.
I have Shared my Inout & output result below, could you please help me how to write query for this.
Scenario
Product
AlgoKey
User Select
SystemSelect
1
P101
1
0
1
1
P102
2
1
0
2
P101
1
0
1
2
P102
2
0
0
3
P101
1
1
1
3
P102
2
0
0
4
P101
1
0
0
4
P102
2
0
1
OutPut :
Scenario
AlgoKey
Columnselected
1
2
User
2
1
System
3
1
User
4
2
System
here is how you can do it
select scenario , AlgoKey, case when Userselect = 1 then 'User' else 'System' end Columnselected
from (
select *, ROW_NUMBER() over (partition by scenario,productkey order by userselect desc, systemselect desc) rn
from tableName
) t
where rn = 1

SQL merge 3 tables

I have an sql query involving 2 tables and try to add a third one.
These are the tables
FreeBookPos
FreeBooK_ID
ArticleNr
Amount
FreeBook
ID
BookNr
Date
FreeFields
FreeFieldType
Value
SQLPrimeKey
The first two are linked this way
select FreeBookPos.ArticleNr, Format(FreeBooking.Date, 'yyyy_MM') as dt,
SUM(CASE WHEN FreeBook.BookNr = 0 THEN FreeBookPos.Amount ELSE 0 END) as TotalEntryAmount,
SUM(CASE WHEN FreeBook.BookNr = 1 THEN FreeBookPos.Amount ELSE 0 END) as TotalLeftAmount
From FreeBookPos
INNER JOIN FreeBook on FreeBookPos.FreeBook_ID = FreeBook.ID
group by FORMAT ( FreeBook.Date, 'yyyy_MM'), FreeBookPos.ArticleNr
order by dt, ArticleNr
Now I need to add the table 3. This table is linked via SQLPrimeKey to FeeBook table ID. I then need to have only the fields where FreeFields.Value 2 or 4 and FreeFields.FreeFieldType = 54.
I tried various options with join but never get the result. Would I need to first join table 2 and 3 and then with 1 in a separate step?
Table 1: FreeBookPos
FreeBook_ID ArticleNr Amount
1 145 12
2 145 6
3 143 4
4 145 1
5 145 42
Table 2: FreeBook
ID BookNr Date
1 1 2012-05-19
2 -1 2012-05-21
3 1 2012-05-22
4 -1 2012-05-24
5 -1 2012-06-25
Table 3: FreeFields
SQLPrimareyKey FreeFieldType Value
1 54 1
2 52 2
3 54 4
4 54 2
5 54 2
Result should be:
ArticleNr Dt TotalEntryAmount TotalLeftAmount
143 2012-05 4 0
145 2012-05 0 -1
145 2012-06 0 -42
Try the below -
select FreeBookPos.ArticleNr, Format(FreeBooking.Date, 'yyyy_MM') as dt,
SUM(CASE WHEN FreeBook.BookNr = 0 THEN FreeBookPos.Amount ELSE 0 END) as TotalEntryAmount,
SUM(CASE WHEN FreeBook.BookNr = 1 THEN FreeBookPos.Amount ELSE 0 END) as TotalLeftAmount
From FreeBookPos
INNER JOIN FreeBook on FreeBookPos.FreeBook_ID = FreeBook.ID
inner join FreeFields on FreeBook.ID=SQLPrimareyKey
where value in (2,4) and FreeFieldType = 54
group by FORMAT ( FreeBook.Date, 'yyyy_MM'), FreeBookPos.ArticleNr
order by dt, ArticleNr

SQL Query. limit an update per rows if condition is X and Y for the same ID number

Have the following table tblTrans where
Trans_ID Trans Sequence Trans_PointsEarned Trans_PointsApplied
4452 1 1 1
4452 2 1 1
4452 3 0 1
4462 1 1 1
4462 2 1 1
4462 3 1 1
4462 4 1 1
4462 5 1 1
9101 1 0 1
9101 2 0 1
9101 3 0 1
9101 4 0 1
(useless table doesnt work)
I need to set the following on another field per every customer ID.
So Customer_OverallPoints
4452 = 2 (doesn't count 0's)
4462 = 4 (I want to cap the points to 4 based on the sequence and transID and customerID)
9101 = 0 (dont count 0's).
This needs to be applied to thousands of records based on customerID and TransID where Trans_Sequence is within the same Trans_ID and it only counts the first 4 rows that have the Trans_pointsEarned = 1.
I tried putting a psuedocode together but it just looked ridicilous and I can't even come up with the logic for this.
Thanks
Assuming that TransId is really the customer id, I think the basic logic is just an aggregation:
select t.TransId,
(case when sum(t.Trans_PointsEarned) > 4 then 4
else sum(t.Trans_PointsEarned)
end) as Customer_OverallPoints
from tblTrans t
group by t.TransId;
You can put this into an update statement as:
update customers c
set Customer_OverallPoints = (select (case when sum(t.Trans_PointsEarned) > 4 then 4
else sum(t.Trans_PointsEarned)
end)
from tblTrans t
where t.TransId = c.CustomerId
);

Need Monthly Report in sql server query

I have 2 tables(Product1, product2).
Product1 Product2
------------------------------ -------------------------------------
PID ProdDesc ProdCode Date PID
------------------------------ -------------------------------------
1 Sony s001 2013/01/21 1
2 Samsung sa01 2013/02/27 1
3 LG L001 2013/03/14 2
4 Toshiba T001 2013/04/18 3
5 Philips P001 2013/05/30 4
2013/06/12 5
I need to generate a query that joins the data from the 2 tables and groups the results by month.
Here is my desired Output:
ProdDesc Jan2013 Feb2013 Mar2013 Apr2013 May2013 Jun2013 Jul2013 Aug2013 Sep2013 Oct2013 Nov2013 Dec2013
--------------------------------------------------------------------------------------------------
Sony 1 1 0 0 0 0 0 0 0
Samsung 0 0 1 0 0 0 0 0 0
LG 0 0 0 1 0 0 0 0 0
Toshiba 0 0 0 0 1 0 0 0 0
Philips 0 0 0 0 0 1 0 0 0
You'll need to use a PIVOT to project your result in columns, although some manipulation is required to prepare the data beforehand, to generate your column names and group data per month:
SELECT ProdDesc, [Jan2013],[Feb2013],[Mar2013],[Apr2013],
[May2013],[Jun2013]
FROM
(
SELECT ProdDesc, YearMonth, COUNT(P2PID) AS ProdCount
FROM
(
SELECT p1.ProdDesc,
CAST(DATENAME(MONTH, [DATE]) AS VARCHAR(3)) +
DATENAME(YEAR, [DATE]) AS YearMonth,
p2.PID as P2PID
FROM Product1 p1
LEFT JOIN Product2 p2
ON p1.PID = p2.PID
) x
GROUP BY ProdDesc, YearMonth
) y
PIVOT
(
SUM(ProdCount)
for [YearMonth] IN ([Jan2013],[Feb2013],[Mar2013],
[Apr2013],[May2013],[Jun2013])
) pv;
SqlFiddle here
It is quite likely that you'll want to determine the columns (MonYYYY) dynamically. Have a look here on how to do this.
You can use ISNULL or COALESCE to replace NULLS in the output, if necessary ISNULL([Jan2013], 0) AS Jan2013