sql program with Group by 2 attributes and 1 condition (Import) - sql

I have a text file that contains Candy issued data.
File contains customer id, issue date, candy name.
C1,2014-01-01,Candy1
C1,2014-01-02,Candy2
C2,2002-06-01,Candy2
C1,2014-01-02,Candy3
C2,2002-06-01,Candy3
I am trying to figure out how can I write a program that creates a list of pairs of candies which were issued together i.e. issued to the same customer on the same day at least twenty-five different times.
Thanks in advance.

--create a table to hold our data
create table CandySales
(
CustomerId nchar(2)
, SaleDate Date
, CandyId nvarchar(10)
)
--upload the data from the csv
bulk insert CandySales
from 'c:\temp\myCsv.csv'
with (fieldterminator = ',', rowterminator = '\n')
--query the data
;with cte as
(
select customerId, candyId, saleDate
from CandySales
group by customerId, candyId, saleDate
having COUNT(1) >= 25
)
select distinct
a.CandyId Item1
, b.CandyId Item2
from cte a
inner join cte b
on a.CandyId > b.CandyId
and a.SaleDate = b.SaleDate
and a.CustomerId = b.CustomerId
Explanation of Query
The cte creates a list of all candies which have had 25 or more sales to the same customer on the same day.
include distinct as we may have the same pair returned for multiple dates/customers; we only want each pair once.
on a.CandyId > b.CandyId is used as we want to ensure the pair contains different candies from one another. We use > instead of != to avoid getting the same pair with item1 and item2 reversed.
we then join on sale date and customer date as we want items which were sold to the same customer on the same day.

Related

SQL SELECT filtering out combinations where another column contains empty cells, then returning records based on max date

I have run into an issue I don't know how to solve. I'm working with a MS Access DB.
I have this data:
I want to write a SELECT statement, that gives the following result:
For each combination of Project and Invoice, I want to return the record containing the maximum date, conditional on all records for that combination of Project and Invoice being Signed (i.e. Signed or Date column not empty).
In my head, first I would sort the irrelevant records out, and then return the max date for the remaining records. I'm stuck on the first part.
Could anyone point me in the right direction?
Thanks,
Hulu
Start with an initial query which fetches the combinations of Project, Invoice, Date from the rows you want returned by your final query.
SELECT
y0.Project,
y0.Invoice,
Max(y0.Date) AS MaxOfDate
FROM YourTable AS y0
GROUP BY y0.Project, y0.Invoice
HAVING Sum(IIf(y0.Signed Is Null,1,0))=0;
The HAVING clause discards any Project/Invoice groups which include a row with a Null in the Signed column.
If you save that query as qryTargetRows, you can then join it back to your original table to select the matching rows.
SELECT
y1.Project,
y1.Invoice,
y1.Desc,
y1.Value,
y1.Signed,
y1.Date
FROM
YourTable AS y1
INNER JOIN qryTargetRows AS sub
ON (y1.Project = sub.Project)
AND (y1.Invoice = sub.Invoice)
AND (y1.Date = sub.MaxOfDate);
Or you can do it without the saved query by directly including its SQL as a subquery.
SELECT
y1.Project,
y1.Invoice,
y1.Desc,
y1.Value,
y1.Signed,
y1.Date
FROM
YourTable AS y1
INNER JOIN
(
SELECT y0.Project, y0.Invoice, Max(y0.Date) AS MaxOfDate
FROM YourTable AS y0
GROUP BY y0.Project, y0.Invoice
HAVING Sum(IIf(y0.Signed Is Null,1,0))=0
) AS sub
ON (y1.Project = sub.Project)
AND (y1.Invoice = sub.Invoice)
AND (y1.Date = sub.MaxOfDate);
Write A SQL query, which should be possible in MS-Access too, like this:
SELECT
Project,
Invoice,
MIN([Desc]) Descriptions,
SUM(Value) Value,
MIN(Signed) Signed,
MAX([Date]) "Date"
FROM data
WHERE Signed<>'' AND [Date]<>''
GROUP BY
Project,
Invoice
output:
Project
Invoice
Descriptions
Value
Signed
Date
A
1
Ball
100
J.D.
2022-09-20
B
1
Sofa
300
J.D.
2022-09-22
B
2
Desk
100
J.D.
2022-09-23
Note: for invoice 1 on project A, you will see a value of 300, which is the total for that invoice (when grouping on Project='A' and Invoice=1).
Maybe I should have used DCONCAT (see: Concatenation in between records in Access Query ) for the Description, to include 'TV' in it. But I am unable to test that so I am only referring to this answer.
Try joining a second query:
Select *
From YourTable As T
Inner Join
(Select Project, Invoice, Max([Date]) As MaxDate
From YourTable
Group By Project, Invoice) As S
On T.Project = S.Project And T.Invoice = S.Invoice And T.Date = S.MaxDate

Use query result

I´m having issues with the following query. I have two tables; Table Orderheader and table Bought. The first query I execute gives me, for example, two dates. Based on these two dates, I need to find Production data AND, based on the production data, I need to find the Bought data, and combine those data together. Lets say I do the following:
Select Lotdate From Orderheader where orhsysid = 1
This results in two rows: '2019-02-05' and '2019-02-04'. Now I need to do two things: I need two run two queries using this result set. The first one is easy; use the dates returned and get a sum of column A like this:
Select date, SUM(Amount) from Orderheader where date = Sales.date() [use the two dates here]
The second one is slighty more complicated, I need to find the last day where something has been bought based on the two dates. Production is everyday so Productiondate=Sales.date()-1. But Bought is derived from Productionday and is not everyday so for every Productionday it needs to find the last Boughtday. So I can't say where date = Orderheader.date. I need to do something like:
Select date, SUM(Amount)
FROM Bought
WHERE date = (
SELECT top 1 date
FROM Bought
WHERE date < Orderheader.date)
But twice, for both the dates I got.
This needs to result in 1 table giving me:
Bought.date, Bought.SUM(AMOUNT), Orderheader.date, Orderheader.SUM(AMOUNT)
All based on the, possible multiple, Lotdate(s) I got from the first query from Sales table.
I've been struggling with this for a moment now, using joins and nested queries but I can't seem to figure it out!
Example sample:
SELECT CONVERT(date,ORF.orfDate) as Productiedatum, SUM(orlQuantityRegistered) as 'Aantal'
FROM OrderHeader ORH
LEFT JOIN OrderFrame ORF ON ORH.orhFrameSysID = ORF.orfSysID
LEFT JOIN OrderLine ORL ON ORL.orhSysID = ORH.orhSysID
LEFT JOIN Item ON Item.itmSysID = ORL.orlitmSysID
where CONVERT(date,ORF.orfDate) IN
(
SELECT DISTINCT(CONVERT(date, Lot.lotproductiondate)) as Productiedatum
FROM OrderHeader ORH
LEFT JOIN Registration reg ON reg.regorhSysID = ORH.orhSysID
LEFT JOIN StockRegistration stcreg ON stcreg.stcregRegistrationSysID = reg.regSysID
LEFT JOIN Lot ON Lot.lotSysID = stcregSrclotSysID
WHERE ORH.orhSysID = 514955
AND regRevokeRegSysID IS NULL
AND stcregSrcitmSysID = 5103
)
AND ORL.orlitmSysID = 5103
AND orldirSysID = 2
AND NOT orlQuantityRegistered IS NULL
GROUP BY Orf.orfDate
Sample output:
Productiedatum Aantal
2019-02-05 20
2019-02-06 20
Here I used a nested subquery to get the results from 'Production' (orderheader) because I just can use date = date. I'm struggling with the Sales part where I need to find the last date(s) and use those dates in the Sales table to get the sum of that date.
Expected output:
Productiedatum Aantal Boughtdate Aantal
2019-02-04 20 2019-02-01 55
2019-02-05 20 2019-02-04 60
Try this.
IF OBJECT_ID('tempdb..#Production') IS NOT NULL DROP TABLE #Production
IF OBJECT_ID('tempdb..#Bought') IS NOT NULL DROP TABLE #Bought
CREATE table #Production(R_NO int,ProductionDate datetime,ProductionAmount float)
CREATE table #Bought(R_NO int,Boughtdate datetime,Boughtamount float)
insert into #Production(ProductionDate,ProductionAmount,R_NO)
select p.date ProductionDate,sum(Amount) ProductionAmount,row_number()over (order by p.date) R_NO
from Production P
join Sales s on p.date=S.date-1
where orhsysid=1
group by p.date
declare #loop int,#ProdDate datetime
select #loop =max(R_NO) from #Production
while (1<=#loop)
begin
select #ProdDate=ProductionDate from #Production where r_no=#loop
insert into #Bought(Boughtdate,Boughtamount,R_NO)
select Date,Sum(Amount),#loop R_NO from Bought where date=(
select max(date) from bought B
where B.Date<#ProdDate)
group by Date
set #loop=#loop-1
end
select ProductionDate,ProductionAmount,Boughtdate,Boughtamount from #Bought B
join #Production p on B.R_NO=P.R_NO

Get Sum of quantities from multiple tables?

I have at least 8 tables from where I need to match the customer name and fetch the quantities and get the sum of all the quantities fetched from these 8 tables. I am trying to write a code which will ignore the customer whose sum of quantities is zero.
For an example lets take two tables purchase_sugar and sales_sugar I have tried a lot of queries but only this one is returning some result which is wrong.
SELECT sum(purchase_sugar.qty + sales_sugar.qty) AS Total_Amount from purchase_sugar inner join sales_sugar on purchase_sugar.supplier = sales_sugar.customer WHERE purchase_sugar.supplier = "+str(x.id)+"
The Table structures are like:
purchase_sugar have two columns supplier and qty.
And sales_sugar have structure like customer and qty.
How can I get the SUM of QUANTITIES of these tables if I provide one name and search it through these tables and get the quantities. The other thing is that I dont want the customer to be found in all the tables. If it is found in one table we should just get the quantity from that one table and for that reason I don't think that JOIN is useful or may be i am wrong.
To take care of the situation where a supplier/customer is not in all the tables, you can use union all and group by:
select name, sum(p_qty) as sum_p, sum(s_qty) as sum_s,
sum(p_qty) + sum(s_qty)
from ((select ps.supplier as name, ps.qty as p_qty, 0 as s_qty
from purchase_sugar ps
) union all
(select ss.customer as name, 0, ss.qty
from sales_sugar ss
)
) s
group by name;
Notes:
This query gets results for all names. You can use a where clause to restrict the results to one name.
You don't have to split the quantities into two (or eight) different columns, if you just want the overall sum.
You can aggregate before the union all, but that is not necessary.
you should JOIN the sum and not sum the join
select t1.purchase_sum + sales_sum as Total_Amount
from (
select purchase_sugar.supplier, sum(purchase_sugar.qty) as purchase_sum
from purchase_sugar
group by purchase_sugar.supplier
) t1
inner join (
select sales_sugar.customer, sum(sales_sugar.qty) as sales_sum
from sales_sugar
group by sales_sugar.customer
) t2 on t1.supplier = t2.customer and t1.supplier = "+str(x.id)+"

SQL Grouping / Contract Value

I know this is going to be a simple one but after a midnight run at other coding my SQL brain is fried so I'm just reaching out for some quick help. I've got a test table with Agent, AgentID, Parent Account, AccountID, and TCV. What I need to do is pull all the agent/account IDs where the AccountIDs belong to an aggregate parent account under that agents name >= 10K.
So in this example, John has 2 accounts under the parent account ABC123 and since their total value is >=10K, these 2 would get pulled. But notice below where Jane has 2 accounts likewise under ABC123 but b/c their total value in her name is < 10K, they would not be pulled. So the results would be something like this:
Essetially I need to pull all AccountIDs where the total value of the parent account they roll-up to for that person is >= 10K. BTW, I'm using SQL Server Management Studio R2.
You just do a simple group by/having to get a list of agentids/parentaccounts that meet the 10k criteria. Then you can use that in a sub-select to join back to the same table and get the list of account ids
select agentid, accountid
from table t
inner join (
select agentid, parentaccount
from table
group by agentid, parentaccount
having sum(tcv) >= 10000
) t1
on t.agentid = t1.agentid
and t.parentaccount = t1.parentaccount
;WITH MyCTE AS
(
SELECT AgentID,
ParentAccount,
SUM(TCV) AS Total
FROM TableName
GROUP BY AgentID,
ParentAccount
)
SELECT T.AgentId, T.AccountId
FROM Table T
JOIN MyCTE M
ON M.AgentId = T.AgentId
AND M.ParentAccount= T.ParentAccount
WHERE M.Total>10000

Display full records of duplicate entries across multiple columns

I have a table (customers) that includes fields telephone_1, telephone_2, telephone_3 & telephone_4.
What I need to see is full records of where any telephone numbers are used in other customers - as I believe something has gone wrong with the data somewhere and customer numbers are duplicated into each other!
I have tried the below code, but this doesn't give me what I want as only compares 1/1, 2/2, 3/3 & 4/4. I have an ID field which can be used to differentiate between records.
SELECT *
FROM Customers AS a
WHERE 1 < (SELECT Count(*)
FROM Customers AS b
WHERE a.Telephone_1 = b.Telephone_1
OR a.Telephone_2 = b.Telephone_2
OR a.Telephone_3 = b.Telephone_3
OR a.Telephone_4 = b.Telephone_4
Any assistance is appreciated - thanks!
How about this?
SELECT *
FROM Customers AS a
WHERE 1 < (
SELECT Count(*)
FROM Customers AS b
WHERE a.Telephone_1 IN (b.Telephone_1, b.Telephone_2, b.Telephone_3, b.Telephone_4)
OR a.Telephone_2 IN (b.Telephone_1, b.Telephone_2, b.Telephone_3, b.Telephone_4)
OR a.Telephone_3 IN (b.Telephone_1, b.Telephone_2, b.Telephone_3, b.Telephone_4)
OR a.Telephone_4 IN (b.Telephone_1, b.Telephone_2, b.Telephone_3, b.Telephone_4)
)
========Take 2=======
Following the comments:
Create a new table with telephone numbers nd customer IDs
CREATE TABLE tempTelephoneNos (
INTEGER customer,
VARCHAR(32) telephoneNo
);
assuming those are the appropriate data types for the customer Id and phone no.
Populate the new table
INSERT INTO tempTelephoneNos (customer, telephoneNo)
SELECT customer_id, telephone_1
FROM customers
UNION ALL
SELECT customer_id, telephone_2
FROM customers
UNION ALL
SELECT customer_id, telephone_3
FROM customers
UNION ALL
SELECT customer_id, telephone_4
FROM customers
Then you can find out which telephone numbers appear for more than one customer with
SELECT customer, telephoneNo
FROM tempTelephoneNos
WHERE 1 < (SELECT COUNT(*) FROM tempTelephoneNos GROUP BY telephoneNo)