Use query result - sql

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

Related

How to join table is sql?

I have two tables which name shoes_type and shoes_list. The shoes_type table includes shoes_id, shoes_size, shoes_type, date, project_id. Meanwhile, on the shoes_list table, I have shoes_quantity, shoes_id, shoes_color, date, project_id.
I need to get the sum of shoes_quantity based on the shoes_type, shoes_size, date, and also project_id.
I get how to sum the shoes_quantity based on color by doing:
select shoes_color, sum(shoes_quantity)
from shoes_list group by shoes_color
Basically what I want to see is the total quantity of shoes based on the type, size, date and project_id. The type and size information are available on shoes_type table, while the quantity is coming from the shoes_list table. I expect to see something like:
shoes_type shoes_size total quantity date project_id
heels 5 3 19/10/02 1
sneakers 5 3 19/10/02 1
sneakers 6 1 19/10/05 1
heels 7 5 19/10/03 1
While for the desired result, I have tried:
select shoes_type, shoes_size, date, project_id, sum(shoes_quantity)
from shoes_type st
join shoes_list sl
on st.project_id = sl.project_id
and st.shoes_id = sl.shoes_id
and st.date = sl.date
group by shoes_type, shoes_size, date, project_id
Unfortunately, I got an error that says that the column reference "date" is ambiguous.
How should I fix this?
Thank you.
The date column exists in both tables, so you have to specify where to select it from. Replace date with shoes_type.date or shoes_list.date
Qualify all column references to remove the "ambiguous" column error:
select st.shoes_type, st.shoes_size, st.date, st.project_id, sum(slshoes_quantity)
from shoes_type st join
shoes_list sl
on st.project_id = sl.project_id and
st.shoes_id = sl.shoes_id and
st.date = sl.date
group by st.shoes_type, st.shoes_size, st.date, st.project_id;
If you want all columns from shoes_type, you might find that a correlated subquery is faster:
select st.*,
(select sum(slshoes_quantity)
from shoes_list sl
where st.project_id = sl.project_id and
st.shoes_id = sl.shoes_id and
st.date = sl.date
)
from shoes_type st;

How to Return a Query Result Even When Nothing Comes Up for the Results

I have a table called "orders" with the following data:
Date Order_No Ship_Method
-------------------------------------
12/6/2013 1234567 RTS
12/6/2013 7654321
12/7/2013 3456789 RTS
12/7/2013 9876543
12/7/2013 1123456 RTS
12/7/2013 5523847 RTS
12/8/2013 8876549
12/8/2013 7733654
I need a query that will search for how many rows of data have "RTS" in the Ship_Method field and return the following result for the day I run the query (like below):
Date RTS_Shipments
-------------------------
12/8/2013 0
-Anthony C.
EDIT
The query that works for me concerning the above issue is the following (provded by Carth in the answers section):
select
sub.tdate,
count(orders.dt)
from (select to_date(to_char((sysdate-1),'mmddYYYY'),'mmddYYYY') tdate from dual) sub
left join orders on sub.tdate = orders.dt and orders.ship_method like '%RTS%'
group by sub.tdate
In order to get the result you need here you will be required to create a basis for your select in which the term you're filtering on definitively exists and then use that to join to your target table. In my initial answer I was thinking that you could select a variable value directly from dual but since I can't get the syntax of that to work out correctly here are a couple of other ideas. You could create a new "working" table that has all the dates you want to check and then select against that and left join to your target table, or you could create a subselect to hold your intended value and use that as the basis of your statement like this:
select
sub.tdate,
count(orders.dt)
from (select to_date(to_char((sysdate-1),'mmddYYYY'),'mmddYYYY') tdate from dual) sub
left join orders on sub.tdate = orders.dt and orders.ship_method like '%RTS%'
group by sub.tdate
You can use a left join on the same table to get all results and the results that you need. The one that you need you sum 1 and 0 for the one you don't.
That should do.
SELECT to_char(o1.DT, 'MM/DD/YYYY') As "Date",
SUM(case when o1.Ship_Method is null then 0 else 1 end) As RTS_Shipments
FROM orders o1
left join orders o2
on (o1.dt = o2.dt and o2.Ship_Method like '%RTS%')
WHERE trunc(o1.DT) = trunc(SYSDATE)
GROUP BY to_char(o1.DT, 'MM/DD/YYYY')
See it at fiddle: http://sqlfiddle.com/#!4/fd374/6
I've changed the date field to dt because date is a reserved word.
And also. This query can count every date but it will show just the registries for the day you filter: trunc(o1.DT) = trunc(SYSDATE) if you take out this condition you will see every date with the proper count.

Count the number of occurrences grouped by some rows

I have made a query to bring me the number of products that have not been in stock (I know that by looking at the orders which the manufacturer returned with some status code), by product, date and storage, that looks like this:
SELECT count(*) as out_of_stock,
prod.id as product_id,
ped.data_envio::date as date,
opl.id as storage_id
from sub_produtos_pedidos spp
left join cad_produtos prod ON spp.ean_produto = prod.cod_ean
left join sub_pedidos sp ON spp.id_pedido = sp.id
left join pedidos ped ON sp.id_pedido = ped.id
left join op_logisticos opl ON sp.id_op_logistico = opl.id
where spp.motivo = '201' -- this is the code that means 'not in inventory'
group by storage_id,product_id,date
That produces an answer like this:
out_of_stock | product_id | date | storage_id
--------------|------------|-------------|-------------
1 | 5 | 2012-10-16 | 1
5 | 4 | 2012-10-16 | 2
Now I need to get the number of occurrences, by product and storage, of products that have been out of stock for 2 or more days, 5 or more days and so on.
So I guess I need to do a new count on the first query, aggregating the resultant rows in some defined day intervals.
I tried looking at the datetime functions in Postgres (http://www.postgresql.org/docs/7.3/static/functions-datetime.html), but couldn't find what I need.
May be I didn't get correctly you question, but it looks you need leverage sub-query.
Now I need to get the number of occurrences, by product and storage, of products that have been out of stock for 2 or more days
So:
SELECT COUNT(*), date, product_id FROM ( YOUR BIG QUERY IS THERE ) a
WHERE a.date < (CURRENT_DATE - interval '2' day)
GROUP BY date, product_id
Since you seem to want every row in the result individually, you cannot aggregate. Use a window function instead to get the count per day. The well known aggregate function count() can also serve as window aggregate function:
SELECT current_date - ped.data_envio::date AS days_out_of_stock
,count(*) OVER (PARTITION BY ped.data_envio::date)
AS count_per_days_out_of_stock
,ped.data_envio::date AS date
,p.id AS product_id
,opl.id AS storage_id
FROM sub_produtos_pedidos spp
LEFT JOIN cad_produtos p ON p.cod_ean = spp.ean_produto
LEFT JOIN sub_pedidos sp ON sp.id = spp.id_pedido
LEFT JOIN op_logisticos opl ON opl.id = sp.id_op_logistico
LEFT JOIN pedidos ped ON ped.id = sp.id_pedido
WHERE spp.motivo = '201' -- code for 'not in inventory'
ORDER BY ped.data_envio::date, p.id, opl.id
Sort order: Products having been out of stock for the longest time first.
Note, you can just subtract dates to get an integer in Postgres.
If you want a running count in the sense of "n rows have been out of stock for this number of days or more", use:
count(*) OVER (ORDER BY ped.data_envio::date) -- ascending order!
AS running_count_per_days_out_of_stock
You get the same count for the same day, peers are lumped together.

Subselect on date

In an Access database there are two tables.
Table one containing Articles and table two contains Prices.
So Articles is the description of all articles and the prices
table just contains an article number, a date date and a price.
If a prices changes, there will be added a new row to prices.
The prices have a date from which on that price shall be used.
Now I want to get the prices that were valid on 01. Oct 2012.
I used my query on current prices and added and prsdat<#02/10/2012#
to the subselect in the query.
Here is what I already have:
SELECT
Articles.ARTNR,
Articles.TXT,
Articles.ACTIVE,
Prices.PRICE,
Prices.PRSGR,
Prices.PRSDAT
FROM
Articles INNER JOIN Prices ON Articles.ARTNR = Prices.ARTNR
WHERE
(((Articles.ACTIVE)="Y") AND
((Prices.PRSGR)=0) AND
((Prices.PRSDAT)=
(SELECT
max(prsdat)
FROM
Prices as art
WHERE
art.artnr = Prices.artnr and prsdat<#02/10/2012#)))
ORDER BY
Articles.ARTNR;
Now the select returns articles that I did not see with this select
I used before, having just added and prsdat<#01/10/2012#.
The result is now 430 articles, before I just had about 260.
The prices returned are older, but I'm not sure about the date format.
In the table I see DD.MM.YYYY, and in the query i shall use MM/DD/YYYY or DD/MM/YYYY?
What is the correct form of this select?
SELECT
a.ARTNR
, a.TXT
, a.ACTIVE -- dubious, since it is constant
, p.PRICE
, p.PRSGR -- dubious, since it is constant
, p.PRSDAT
FROM Articles a
INNER JOIN Prices p ON a.ARTNR = p.ARTNR
WHERE a.ACTIVE = 'Y'
AND p.PRSGR = 0
AND p.prsdat < #02/10/2012#
AND NOT EXISTS (
SELECT *
FROM Prices nx
WHERE nx.ARTNR = p.ARTNR
AND nx.PRSGR = 0
AND nx.prsdat < #02/10/2012#
AND nx.prsdat > p.prsdat
)
ORDER BY
Articles.ARTNR
;

Need a little help, SQL Server 2000, having and max(date)

I need a little help getting this script doing what I want it to.
SELECT KM.initials,
TPL.debprice,
TMP.pricegroup,
TMP.date
FROM klientmedarbejder KM
INNER JOIN timeprismedarbejderprisgruppe TMP
ON KM.employeeno = TMP.employeeno
INNER JOIN timeprisprisgruppelinie TPL
ON TMP.pricegroup = TPL.pricegroup
GROUP BY KM.initials,
TMP.date,
TPL.debprice,
TMP.pricegroup,
TPL.date
HAVING ( Max(TMP.dato) = TPL.date )
What I need is the debPrice with the latest (max) date. An employee goes through his career, once in a while his price gets upgraded. Price gets selected from a set list of prices.
KlientMedarbejder is the employee table.
TimeprisMedarbejderPrisgruppe is the list of date his record get upgrade to the new price.
TimeprisPrisgruppeLinie is the list of prices you can have.
I have the solution down to 2 options per employee. Hence:
emp A - 300 - 9 - 1900-01-01
emp A - 500 - 4 - 2012-01-01
emp B - 400 - 6 - 1900-01-01
emp B - 800 - 8 - 2012-04-01
Hence, first record is the default from whenever he joined the company. In 2012 he was finally good enough for a better price tag. Now I need the answer with the latest date on the upgrade list for each employee. Hence emp A should give me 500 and emp B should give me 800. Now not all employees may have had the 01-01 or 04-01 price update. Some employees have had up to 8 upgrades over time, I only care for the latest.
Client I'm pulling this data from is running an SQL Server 2000.
The typical solution for SQL Server 2000 is to isolate the employeeno and their max date (this is much easier in 2005+). Pseudo-code:
SELECT d.columns, etc. FROM
(
SELECT employeeno, [date] = MAX([date])
FROM dbo.tablewithdates
GROUP BY employeeno
) AS grouped_emp
INNER JOIN dbo.tablewithdates AS d
ON d.employeeno = grouped_emp.employeeno
AND d.[date] = grouped_emp.[date]
INNER JOIN ...
The danger is if employeeno + date is not unique, you could get multiple rows, so you need to determine how to deal with ties.
I would write it for your schema but I can't reverse engineer your query to figure out which table is which. Start simple and work up.
The HAVING clause takes place after the group by, so it can only use aggregated columns.
You need to calcualte the max date before the group by. This requires adding in a subquery for the calculation and then a WHERE clause to do the right filtering:
SELECT KM.initials, TPL.debprice, TMP.pricegroup, TMP.date
FROM klientmedarbejder KM INNER JOIN
timeprismedarbejderprisgruppe TMP
ON KM.employeeno = TMP.employeeno INNER JOIN
timeprisprisgruppelinie TPL
ON TMP.pricegroup = TPL.pricegroup join
(select employeeno, MAX(dato) as maxdato
from timeprismedarbejderprisgruppe t
group by employeeno
) tmax
on tmax.employeeno = tmp.employeeno
where tmp.dato = tmax.maxdato
GROUP BY KM.initials, TMP.date, TPL.debprice, TMP.pricegroup, TPL.date