SELECTING with multiple WHERE conditions on same table - sql

I am currently working on my sql query that looks like this
SELECT reference.agent_ID, reference.policy_ID, Count(reference.status_ID) AS [Quoted Motor Breakdown] , Sum(IIf([status_ID]=1,1,0)) AS sold
FROM reference
GROUP BY reference.agent_ID, reference.policy_ID
HAVING (((reference.policy_ID)=1));
So results show as below
Agent| Number of policies quoted for Motor breakdown|number of policies Motor breakdown sold
I would like to add more columns to the same table showing results for remaining type of policies :
reference.policy_ID=2 (Travel),
reference.policy_ID=3 (Home Insurance) next to one agent
example:
Mr Smith|Quoted Motor Breakdown| Sold| Quoted Motor Travel| Sold
I would also like to my query to show result=0 if there wos no quote for specific type of policy
Any advise would be much appreciated
Thank you

I think you want conditional aggregation:
SELECT r.agent_ID,
SUM(CASE WHEN r.policy_ID = 1 THEN 1 ELSE 0 END) AS [Quoted Motor Breakdown],
SUM(CASE WHEN r.policy_ID = 1 AND status_ID = 1 THEN 1 ELSE 0 END) AS sold,
SUM(CASE WHEN r.policy_ID = 2 THEN 1 ELSE 0 END) AS NumTravel,
SUM(CASE WHEN r.policy_ID = 3 THEN 1 ELSE 0 END) AS NumHomeInsurance
FROM reference r
GROUP BY r.agent_ID;
If you are using MS Access, then you'll need to use the non-standard iif() instead:
SELECT r.agent_ID,
SUM(iif(r.policy_ID = 1, 1, 0)) AS [Quoted Motor Breakdown],
SUM(iif(r.policy_ID = 1 AND status_ID = 1, 1, 0)) AS sold,
SUM(iif(r.policy_ID = 2, 1, 0)) AS NumTravel,
SUM(iif(r.policy_ID = 3, 1, 0)) AS NumHomeInsurance
FROM reference as r
GROUP BY r.agent_ID;

Related

A SQL query for the retrieval of result based on input month

Table 1
Table 2
My requirement is to input the Redemption month and list the tickets that has been scanned double or more.
For example Ticket No. T1 has been scanned 2 times under pickup,only once under PickupOutforDelivery and 2 times under Delivery.
Result needed like this:
How can I write a query to get the result like this?
Tried:
SELECT
Ticket,
COUNT(Scantype = 0) AS Pickup,
COUNT(Scantype = 1) AS PickupOutforDelivery,
COUNT(Scantype = 2) AS Delivery
FROM
Scans
GROUP BY
Ticket, ScanType
HAVING
(Pickup > 1 OR PickupOutforDelivery > 1 OR Delivery > 1)
OR (Pickup >= 1 AND PickupOutforDelivery >= 1)
ORDER BY
Ticket
Result
Assuming that RedemptionMonth has a datatype of DATE (which is clearly required); the following query will give you the result you want, except the "cosmetic" part (breaking by year month for the report part) that you have to do on your application:
SELECT YEAR(RedemptionMonth) AS [YEAR], MONTH(RedemptionMonth) AS [MONTH], TicketNo,
COALESCE(SUM(CASE WHEN ScanName = 'Pickup' THEN 1 ELSE 0 END), 0) AS Pickup,
COALESCE(SUM(CASE WHEN ScanName = 'PickupOutForDelivery' THEN 1 ELSE 0 END), 0) AS PickupOutForDelivery ,
COALESCE(SUM(CASE WHEN ScanName = 'Delivery' THEN 1 ELSE 0 END), 0) AS Delivery
FROM [Table 1] AS T1
JOIN [Table 2] AS T2
ON T1.ScanType = T2.ScanType
GROUP BY YEAR(RedemptionMonth) AS [YEAR], MONTH(RedemptionMonth) AS [MONTH], TicketNo
Because you are using the numeric value of scanType, no JOIN is needed. So, the only fix is needed for conditional aggregation:
SELECT Ticket,
SUM(CASE WHEN Scantype = 0 THEN 1 ELSE 0 END) as Pickup,
SUM(CASE WHEN Scantype = 1 THEN 1 ELSE 0 END) as PickupOutforDelivery,
SUM(CASE WHEN Scantype = 2 THEN 1 ELSE 0 END) as Delivery
FROM Scans
WHERE redemptionMonth = 'Jan-21'
GROUP BY Ticket
HAVING Pickup > 1 OR
PickupOutforDelivery > 1 OR
Delivery > 1 OR
(Pickup >= 1 AND PickupOutforDelivery >= 1)
ORDER BY Ticket;
Note that you can add redemptionMonth to the GROUP BY (and SELECT) to get the results for each month.
If redemptionMonth is really a date and not a string, then define the time period using a range of dates:
WHERE redemptionMonth >= '2021-01-01' AND
redemptionMonth < '2021-02-01'

Need to calculate Year wise sum in the desired output format below, but I am getting column wise data

I just need to know that how can I get the row wise- year totals.
Here is my code and need to get the below expected result :
SELECT /*+parallel(v,32) +parallel(mm,32) +parallel(c,32) */
'BUS' VEH_TYPE,
MM.MAKE_MO,
SUM (CASE WHEN SUBSTR (V.YEAR_Val, 1, 4) = '1990' THEN 1 ELSE 0 END)
AS FY1990,
SUM (CASE WHEN SUBSTR (V.YEAR_VAL, 1, 4) = '1991' THEN 1 ELSE 0 END)
AS FY1991,
SUM (CASE WHEN SUBSTR (V.YEAR_VAL, 1, 4) = '1992' THEN 1 ELSE 0 END)
AS FY1992,
SUM (CASE WHEN SUBSTR (V.YEAR_VAL, 1, 4) = '1993' THEN 1 ELSE 0 END)
AS FY1993,
SUM (CASE WHEN SUBSTR (V.YEAR_VAL, 1, 4) = '1994' THEN 1 ELSE 0 END)
AS FY1994,
SUM (CASE WHEN SUBSTR (V.YEAR_VAL, 1, 4) = '1995' THEN 1 ELSE 0 END)
AS FY1995,
COUNT (MM.MAKE_MO) Total_Count
FROM VEHICLE V, MAKE mm, CATEGORY c
WHERE C.MAKE_MO = mm.MAKE_MO
AND c.CATEGORY_CD = v.CATEGORY_CD
AND V.p_MONTH BETWEEN '199001' AND '199501' --using this as data is huge
AND C.TYPE_CODE=01
AND MM.VEH_CODE='B'
GROUP BY 'BUS,'MM.MAKE_MO, V.YEAR_Val
ORDER BY V.YEAR_Val;
This is the Expected Result :
VEH TYPE YEAR MODEL TOTAL
------- ----- --------
Bus 1990 7,808,658
Bus 1991 5,474,809
Bus 1992 54,839,221
Bus 1993 54,680,000
Bus 1994 15,000,000
Bus 1995 17,899,668
This was way too long for a comment. After unwinding this query, it appears that you are simply trying to get a count of 'Bus' vehicles by model year (with ALL vehicles in the VEHICLE table are being labeled 'Bus'). If that's the case, you can simplify your query a lot.
SELECT VEH_TYPE
, theYear AS YEAR_MODEL
, COUNT(*) AS TOTAL
FROM (
SELECT 'BUS' AS VEH_TYPE
, SUBSTR(V.YEAR_Val,1,4) AS theYear
FROM VEHICLE V
INNER JOIN CATEGORY c ON v.CATEGORY_CD = c.CATEGORY_CD
AND C.TYPE_CODE='01'
INNER JOIN MAKE mm ON c.MAKE_MO = mm.MAKE_MO
AND MM.VEH_CODE='B'
WHERE V.p_MONTH BETWEEN '199001' AND '199501'
) s1
WHERE theYear IN ('1990','1991','1992','1993','1994','1995')
GROUP BY theYear
You may not need the WHERE clause if your vehicle years are only 1990-1995. And your JOINed tables don't appear to be doing anything other than limiting your VEHICLE table if there are no CATEGORY_CD matches in VEHICLE and CATEGORY, and if there are no MAKE_MO matches in MAKE and CATEGORY. If you were filtering for a specific column from CATEGORY or MAKE, or you had orphaned records in VEHICLE, then you'd want to add those JOINs back in. Otherwise, I don't think they're really doing anything.
Note that SUBSTR(V.YEAR_Val,1,4) will exclude any index you have on V.YEAR_Val, and if that's a column you need regularly, or if there are a lot of VEHICLE records, you may need to split that value into its own column.

SQL - Group data with same ID and Date that has been to every Machine but has a different Name

I am trying to create a query that will group data by CT ID and Date that have all 3 MachineID's (1, 10, and 20) and at least one different Sawing Pattern Name.
This Image shows a highlighted example of the data I'm trying to get back and the code i'm currently using
I'm trying to only show data similar to the highlighted rows in the image (CT ID 501573833) and exclude the data in the rows around it where the Sawing Pattern Name is the same at all 3 MachineID's.
Your description suggests group by and having. The conditions you describe can all go in the having clause:
select ct_id, date
from t
group by ct_id, date
having sum(case when machineid = 1 then 1 else 0 end) > 0 and
sum(case when machineid = 10 then 1 else 0 end) > 0 and
sum(case when machineid = 20 then 1 else 0 end) > 0 and
min(sawing_pattern_name) <> max(sawing_pattern_name)
Seems to me that an EXISTS could be useful here.
SELECT
[CT ID],
[MachineID],
[Sawing Pattern name],
[Time],
CAST([Time] AS DATE) AS [Date]
FROM [DataCollector].[dbo].[Maxicut] t
WHERE EXISTS
(
SELECT 1
FROM [DataCollector].[dbo].[Maxicut] d
WHERE d.[CT ID] = t.[CT ID]
AND CAST(d.[Time] AS DATE) = CAST(t.[Time] AS DATE)
AND d.[MachineID] != t.[MachineID]
AND REPLACE(d.[Sawing Pattern name],',','') != REPLACE(t.[Sawing Pattern name],',','')
);

Transact SQL - Table with different Record types requiring calculation

I have a table of invoices and Record_Types that I need to reconcile to open invoice report. I have the process down and know what I need to do. Just dont know how to properly structure the query and would prefer to not create 3 tables.
Record Types.
Invoice = 1 Credit = 5 Payment = 7
Invoice_Number, Record_Type, Dollar figure
Outstanding_Balance = Invoice(1) -(Payment(7)-(Credit))
Invoice_number Record_type Gen_Numeric_3
Basically I need to take the record_Type 1 and subtract the total of record type 7's from the below.
Invoice_Num Rec_Type Dollar_Amt
00820437 1 536.7700000000
00820437 7 469.6200000000
00820437 7 67.1500000000
Any advice would be great. messer
You can do this with aggregation and case statements:
SELECT invoice_num,
SUM(CASE WHEN rec_type = 1 THEN dollar_amt ELSE 0 END) - (SUM(CASE WHEN rec_type=7 THEN dollar_amt ELSE 0 END) - SUM(CASE WHEN rec_type=5 THEN dollar_amt ELSE 0 END)) as outstanding_balance
FROM yourtable
GROUP BY invoice_num

SQL Select Query - problem pivoting rows into columns

I have three tables in an SQL 2005 database, that I need to query and display on one row. The tables are:
MasterStock
StockID, Description
1, Plate
2, Bowl
ShopStock
ShopID, StockID, StockLevel
1,1,6
2,1,0
3,1,0
4,1,10
Sales
StockId, ShopId, SoldQuantity, transDate
1, 1, 1, 5/1/2011
1,2,1, 5/1/2011
I need to get them to show one row:
StockID, Description, 1 Sales, 1 Stock, 2 Sales, 2 Stock, 3 Sales,…
I have managed to get what somewhere with the query below:
SELECT MasterStock.StockID, MasterStock.Description,
SUM(CASE WHEN sales.shopid = 1 THEN sales.Soldquantity ELSE 0 END) AS [1 Sold],
MAX(CASE WHEN shopstock.shopid = 1 THEN shopstock.stockLevel ELSE 0 END) AS [1 Stock],
SUM(CASE WHEN sales.shopid = 2 THEN sales.Soldquantity ELSE 0 END) AS [2 Sold],
MAX(CASE WHEN shopstock.shopid = 2 THEN shopstock.stockLevel ELSE 0 END) AS [2 Stock],
SUM(CASE WHEN sales.shopid = 3 THEN sales.Soldquantity ELSE 0 END) AS [3 Sold],
MAX(CASE WHEN shopstock.shopid = 3 THEN shopstock.stockLevel ELSE 0 END) AS [3 Stock],
SUM(CASE WHEN sales.shopid = 4 THEN sales.Soldquantity ELSE 0 END) AS [4 Sold],
MAX(CASE WHEN shopstock.shopid = 4 THEN shopstock.stockLevel ELSE 0 END) AS [4 Stock]
FROM ShopStock INNER JOIN
Sales ON ShopStock.StockID = Sales.StockID AND ShopStock.shopID = Sales.ShopID
INNER JOIN MasterStock ON ShopStock.StockID = MasterStock.StockID
WHERE (sales.transdate > 1/1/2010)
GROUP BY MasterStock.StockID, MasterStock.Description
However, if there are no sales for the product it doesn’t show any stock levels. If I remove the shopID join on shopstock and sales it shows the stock levels, but reports inaccurate sales - multiplies by four (one for each shopstock record?).
I know I’m missing something here, but I’m not getting anywhere! Any help would be greatly received.
Two problems:
1) You need a LEFT OUTER JOIN between ShopStock and Sales, which will ensure that the query returns records from ShopStock even if there are no related entries in Sales. By definition, an INNER JOIN will not return records from either side of the join, if one of the sides is missing records.
2) You need to move your sales.transdate > 1/1/2010 condition to the inner join, rather than the WHERE clause. Conditions in the WHERE clause will be logically applied after any logic in the table joins. So even if you get your joins right, the where clause will filter out stock without sales because sales.transdate will appear null.
Something like this:
FROM ShopStock LEFT OUTER JOIN Sales
ON ShopStock.StockID = Sales.StockID
AND Sales.transdate > 1/1/2010
INNER JOIN // the rest of your joins here
I'm guessing you also want >= on your transdate filter as well, but that's just a hunch.
Good luck!