Looking for help with a TSQL query.
Lets say you are building Kitchen Cabinets. There are numerous parts to build 1 cabinet and a kitchen in turn will have numerous cabinets. Lets also say that we have 3 different types of cabinets (floor, upper and tall).
We have rack(s) where we want to put all the parts required to build the kitchen. However, we want to keep everything organized. So, Cabinet 1, we want to keep all its parts together.
Our Rack has numerous slots (so many per type of cabinet..upper, floor, tall). The slots can only hold so many pieces before it needs to spill over to the next slot.
So our database has a list of all the parts required per cabinet that is needed. The goal is to associate each part with a rack and slot #. We also know that there are cases where 1 cabinet will need numerous slots and a kitchen may require numerous racks.
How can you write a query to do this. Sample data below:
So The goal (referencing the row number - slot number).
1-1, 2-2, 3-3, 4-3, 5-3, 6-3, 7-3, 8-3, 9-4, 10-4......
Cabinet ID 32 needs 3 slots. So we want to show that you are going to start in slot 3, fill it, move to slot 4, fill it and then move on to slot 5.
I have separate tables that tell me how many slots per slot type are in a rack.
I am using the following so far:
SELECT TOP (100) PERCENT dbo.[CAD-CV-Cabinets].[Cabinet ID] ,
dbo.[CAD-CV-Parts].Width ,
dbo.[CAD-CV-Parts].Length ,
dbo.[CAD-CV-MateriaIs].Name ,
dbo.[CAD-CV-Parts].AutoID ,
dbo.[CAD-CV-Cabinets].[Cabinet Type] ,
CASE WHEN [CAD-CV-Parts].Width > 40
OR [CAD-CV-Parts].Width > 40
OR [CAD-CV-Cabinets].[Cabinet Type] IN(3) THEN 'Tall'
WHEN [CAD-CV-Cabinets].[Cabinet Type] IN(1 , 12 , 4 , 5 , 6 , 7) THEN 'Lower'
WHEN [CAD-CV-Cabinets].[Cabinet Type] IN(2 , 9 , 8 , 10 , 11 , 13 , 14) THEN 'Upper'
ELSE 'No Cart' END AS SlotType,
CASE WHEN [CAD-CV-Parts].Width > 40
OR [CAD-CV-Parts].Width > 40
OR [CAD-CV-Cabinets].[Cabinet Type] IN(3)
THEN ceiling(SUM(2) OVER (PARTITION BY [CAD-CV-Cabinets].[Cabinet ID] ORDER BY dbo.[CAD-CV-Parts].AutoID) / (select min(SlotWidth) from CartDetails where SlotType = 'Tall'))
end TallSlotCount FROM dbo.[CAD-CV-Cabinets]
INNER JOIN
dbo.[CAD-CV-Parts]
ON dbo.[CAD-CV-Cabinets].[Cabinet ID] = dbo.[CAD-CV-Parts].CabinetID
INNER JOIN
dbo.[CAD-CV-MateriaIs]
ON dbo.[CAD-CV-Parts].MaterialID = dbo.[CAD-CV-MateriaIs].ID WHERE ([CAD-CV-Parts].Width > 40
OR [CAD-CV-Parts].Width > 40
OR [CAD-CV-Cabinets].[Cabinet Type] IN(3))
and dbo.[CAD-CV-Parts].DoorID = 0
AND dbo.[CAD-CV-Parts].DrawerID = 0
AND dbo.[CAD-CV-Parts].RollOutID = 0
AND dbo.[CAD-CV-Parts].TopID = 0 ORDER BY dbo.[CAD-CV-Cabinets].[Cabinet ID] , dbo.[CAD-CV-Parts].AutoID;
Related
trying to run a script in athena where I can pull back customers who have made purchases of two specified values (14.45 and 17.45). Thought I would make a column for each value appearing and filter out for both columns >0 when downloaded onto excel but my code isn't working, any help.
select order_customer_id,
sum(invoice_total_price= cast('14.45' as decimal(20,2))) > 0,
sum(invoice_total_price = cast('17.45' as decimal(20,2))) > 0
from orders
where year_month_day between '2022-01-10' and '2022-03-14'
group by order_customer_id
Get this error when I run it
Unexpected parameters (boolean) for function sum. Expected: sum(double) , sum(real) , sum(bigint) , sum(interval day to second) , sum(interval year to month) , sum(decimal(p,s))
I done the cast within the two sum columns as the invoice_total_price is stored as decimal
You can use count_if, also potentially cast from string is not needed:
select order_customer_id,
count_if(invoice_total_price = 14.45) > 0 has_14,
count_if(invoice_total_price = 17.45) > 0 has_17
from orders
where year_month_day between '2022-01-10' and '2022-03-14'
group by order_customer_id
Which will give you a table with 3 corresponding columns. If you don't need them in the output you can consider moving checks into HAVING clause:
select order_customer_id
from orders
where year_month_day between '2022-01-10' and '2022-03-14'
group by order_customer_id
having count_if(invoice_total_price = 14.45) > 0
and count_if(invoice_total_price = 17.45) > 0
So I have data that looks like this:
What I am trying to do in SQL is get all of the CollectedDT that are later than a date and less than a date, for example all of the values in yellow in both columns belong together, the records with just one column in yellow I don't care about and the ones in all green are keepers too. The idea is to try and implicitly say that one set of collection times belong to an order and another set belong to the other. There is no rule for hours difference between each, could be 1 hour, could be 100 hours.
While the query returned what it should have, it is decipherable that the CollectedDT of 11-04-2011 15:35 and newer most likely belongs to the 11-03-2011 21:12 order, there is no hard logic to dictate this, it is simply implied and needs to be treated as such.
Really no good starting point on how to go from here.
The query is as follows:
SELECT ORD.[episode_no],
ORD.[ord_no],
ORD.[pty_name] AS 'Ordering Provider',
ORD.[ent_dtime] AS 'Order Entered',
ASMT.[CollectedDT],
ORD.[str_dtime],
ORD.last_cng_dtime,
PMS.vst_start_dtime AS 'Admit Dt',
PMS.[vst_end_dtime] AS 'Discharge Dt',
ORD.[ord_qty],
CASE
WHEN ORD.[ord_sts] = 27
THEN 'Complete'
WHEN ORD.ord_sts = 34
THEN 'Discontinued'
ELSE ORD.ord_sts
END AS 'Order Status',
ORD.[desc_as_written],
ASMT.[FormUsage] AS 'Assessment',
ASMT.[AssessmentID],
datediff(minute, ORD.ent_dtime, ASMT.CollectedDT) AS [order_entry_to_collected_minutes],
datediff(hour, ORD.ent_dtime, ASMT.CollectedDT) AS [order_entry_to_collected_hours]
FROM [SMSPHDSSS0X0].[smsmir].[mir_sr_ord] AS ORD
LEFT OUTER JOIN [smsmir].[mir_sr_vst_pms] AS PMS ON PMS.episode_no = ORD.episode_no
LEFT OUTER JOIN [smsmir].[mir_sc_Assessment] AS ASMT ON ASMT.PatientVisit_oid = PMS.vst_no
WHERE (ORD.desc_as_written LIKE 'physical Therapy%')
AND (
ASMT.FormUsage IN ('Physical Therapy Initial Asmt', 'Physical Therapy Re-evaluation', 'PT Flowsheet')
AND ASMT.CollectedDT > ORD.ent_dtime
)
AND ORD.ord_sts = 27
AND ASMT.AssessmentStatus = 'Complete'
Not even sure if possible but my query is this:
select * from
(select dh.IDFILE as idfile
, sg.XSHCSCMIDFISCIVAIDPAESE as codaziendamittente
, azmitt.ragionesociale as ragsocmitt
, sg.XSHCDPRIDFISCIVAIDPAESE as codaziendadestinatario
, azdest.ragionesociale as ragsocdest
, dh.codcomunita as codcomunita
, sg.xsbdtgnnumero as numerodoc
, sg.codformatodocumento as codformatodocumento
, sg.xsbdtgnddata as datadoc
, sg.xshcdpridfiscivaidcodice as sgmitt
, sg.XSHCDPRCODICEFISCALE as sgmittragsoc
, sg.xshcscmidfiscivaidcodice as sgdest
, sg.XSHCSCMCODICEFISCALE as sgdestragsoc
, da.tipoack
, da.stato as stato
, sg.xsbdtgnddata as datainsert
, sg.dhdatainsert as dataoraricezione
, da.datainsert as datelastupdate
, dh.idrs, sg.identificativosdi as sdi
, sg.tipofile as ciclofatturazione
, ROW_NUMBER() OVER (PARTITION BY dh.idfile, dh.datainsert ORDER BY da.datelastupdate desc) rn
from sogeidoc sg
join datahistoryindex dh on sg.DHIDFILE = dh.IDFILE
and sg.dhdatainsert = dh.datainsert
join datahistoryack da on da.IDFILE = dh.IDFILE
and da.datainsert = dh.datainsert
left join azienda azmitt on dh.codaziendamittente = azmitt.codazienda
and dh.codcomunita = azmitt.codcomunita
left join azienda azdest on dh.codaziendadestinatario = azdest.codazienda
and dh.codcomunita = azdest.codcomunita)
where rn = 1
and codcomunita ='AGRILL'
order by datelastupdate desc OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY
problem: datahistoryack is 143'889'309 records, datahistoryindex is 143'889'309 records and sogeidoc is 19'386'835 records,
in my current java code I execute this query everytime a user make a search and I paginate each page of 100 rows (I only change the offet from 0 to number of page *100 -100). codcomunita is the only mandatory field.
Also the ROW_NUMBER() PARTITION is necessary and I cannot use a materialized view because the user should be able to find data updated in realtime.
There is any way I can solve this problem or there is no way to get a result in, at most, under 10 minutes? Right now it just stay in execution forever.
Any way to optimize this query is also welcome.
I'm not skilled in sql, I just know the basics (I made this query with the help of my tutor at work), and this was working on a much smaller database, but even my tutor said he is not able to solve this problem so I'm stuck. In any answer I will still need lot's of information on how to implement a complex solution since I'm still new to the sql world.
EDIT
DATAHISTORYACK IDFILE 44040192 C2021B C42D212B2B 0,000000022706531343006 6
DATAHISTORYACK DATAINSERT 4756992 78760612110C1F 78770B1B060202 0 8
DATAHISTORYACK CODCOMUNITA 17 4141423242 57494B49 0,00000000346502548460408 7
DATAHISTORYACK DATELASTUPDATE 6566912 78760612110C20 78770B1B060202 0 8
DATAHISTORYINDEX IDFILE 44040192 C102 C42D212C56 0,000000022706531343006 6
DATAHISTORYINDEX DATAINSERT 4757504 7876051D0B1A17 78770B1B061201 0 8
DATAHISTORYINDEX CODCOMUNITA 17 4141423242 57494B49 0,0000000113196238651992 7
DATAHISTORYINDEX DATELASTUPDATE 2656768 7876051D0B1A17 78770B1B061201 0 8
SOGEIDOC CODCOMUNITA 19 4141423242 617574696E76 0,0000000257141209969735 7
SOGEIDOC DATELASTUPDATE 1359360 77B40101010101 78770B1B062E1E 0,000001 8
To provide a good answer I would need:
Histogram data for dh.codcomunita, dh.idfile, dh.datainsert, da.datelastupdate
Estimated result without filter of the query without fetch filters
Execution plan of query
It's a big difference if you search for the last changes of 1'000 files or 1 million.
Isn't it possible to filter on table sogeidoc first. Some information like codcomunita should be in there.
All you need is an index after all joining tables with huge number of records already in each table with overhead query manipulation as via rownumber and partition by takes time. So, all you could do for now is an index on the columns which are unique and which are especially used in your join conditions.
I'm presently making a report on ssrs from a Great Plains Dynamics DB.
It's a pretty simple report with a few columns. Everything works fine but in GP, when creating an Invoice or a Return bill, sometimes GP is gonna give the same Bill ID. It doesn't really shows as a duplicated because for GP, an Invoice and a Return can/could have the same ID because they are not the same type. Don't ask me why..
So for my report, when I start a research from a multiples values parameters with my SopNumber (Bill ID) it gives me the right information. But now I would like to have a flag on those information that equals the bill ID and has Invoice and Return at the same time.
Since it is normal for GP to have 2 different type of document for the same ID, I cannot ask my report to remove the return or the invoice cause in different case, an Invoice could be the important document and in an other case, the return.
In my tablix, I do not show the Bill ID, because I don't need the information except when there is this "duplication".
I would also like after the flag (line highlited), that on the top of my report, a sentence shows something like : "Those documents are in conflict : 000123123". So with this information showing my ID, I can now go in my multiple values parameter and remove this number.
I wanna achieve those 2 flags because I'm making a calcul from my documents amount and if those 2 would be there, it would make my calcul wrong.
I hope you guys can help me. If so, thank you very much in advance!
I worked on a couple of different expressions but never got the result I wanted. Use previous statement and equals but couldn't find how to make it look like is equals to Invoice and Return and SopNumber equals the same.
select CASE SOP10200.SOPTYPE
WHEN 1 THEN 'QUOTE'
WHEN 2 THEN 'ORDER'
WHEN 3 THEN 'INVOICE'
WHEN 4 THEN 'RETURN'
WHEN 5 THEN 'BACK ORDER'
WHEN 6 THEN 'FULLFILLMENT ORDER'
END AS SOPTYPE,
sop10200.SLPRSNID,
sop10200.XTNDPRCE as ExtendedPrice,
sop10200.SOPNUMBE,
iv00101.ITMCLSCD as FAMILYCLASS,
sop10100.DOCDATE
from sop10200
left join iv00101 on sop10200.ITEMNMBR = iv00101.ITEMNMBR
left join sop10100 on sop10200.SOPNUMBE = sop10100.SOPNUMBE
WHERE SOP10100.DOCDATE BETWEEN '2018-01-01 00:00:00.000' AND '2035-01-01 00:00:00.000'
union all
select CASE SOP30300.SOPTYPE
WHEN 1 THEN 'QUOTE'
WHEN 2 THEN 'ORDER'
WHEN 3 THEN 'INVOICE'
WHEN 4 THEN 'RETURN'
WHEN 5 THEN 'BACK ORDER'
WHEN 5 THEN 'FULLFILLMENT ORDER'
END AS SOPTYPE,
sop30300.SLPRSNID,
sop30300.XTNDPRCE as ExtendedPrice,
sop30300.SOPNUMBE,
iv00101.ITMCLSCD as FAMILYCLASS,
sop30200.DOCDATE
from sop30300
left join iv00101 on sop30300.ITEMNMBR = iv00101.ITEMNMBR
left join sop30200 on sop30300.SOPNUMBE = sop30200.SOPNUMBE
WHERE SOP30200.DOCDATE BETWEEN '2018-01-01 00:00:00.000' AND '2035-01-01 00:00:00.000'
ORDER BY SOPNUMBE desc
Correct me if I'm wrong, but it sounds like you want a way to see if there is a duplicate record for the report and use that in a calculation?
You could do a subquery to retrieve a count, and if that is more than 1 than you have a duplicate record
EDIT:
SELECT *, (IF
(SELECT Count(S1.SOPTYPE) FROM sop10200 S1 WHERE T1.BillID = S1.BillID ) > 1 THEN "Duplicate " ELSE "" END) AS DuplicateCheck
FROM sop10200 T1
The above solution will give you a value you can use on each page to report whether or not that it has a duplicate BillID.
I have a query where I'm calculating Days of Therapy for medications. I want to have 0 values to show for months that have no data. Currently the query returns no record if the Sum is 0. Can't seem to figure this out. See the Query Below:
If I were to comment out identifiers related to the DOT_ALL table along with the Where Clause I get 60 rows, 1 for each month for the past 5 years. However, otherwise i get only 57 for the drug in the Where Clause since there are not DOTs for Aug 2016, April 2016 and Jan 2015.
Thanks in advance.
----------------------------------------------------------------------------
SELECT
AMS.[Medication Name]
, SUM(AMS.DOT) AS DOT
, PD.[Patient Days]
, PD.[Month_Name]
, PD.[Fiscal_Month]
, PD.[Accounting_Year]
, PD.[Year]
FROM
DW_PROD.dbo.Patient_Days_By_Month PD
Left JOIN [DW_PROD].[dbo].[DOTS_All] AMS ON (PD.Month_Name = AMS.Month AND PD.Year = AMS.Year)
WHERE
[Medication Name] = 'CEFUROXIME'
GROUP BY
AMS.[Medication Name]
, PD.[Patient Days]
, PD.[Month_Name]
, PD.[Fiscal_Month]
, PD.[Accounting_Year]
, PD.[Year]
ORDER BY
ACCOUNTING_YEAR
,FISCAL_MONTH
This may be the cheapest solution, under the assumption that Patient_Days_By_Month is already some kind of calendar.
SELECT
'CEFUROXIME' AS [Medication Name],
SUM(AMS.DOT) AS DOT,
PD.[Patient Days],
PD.[Month_Name],
PD.[Fiscal_Month],
PD.[Accounting_Year],
PD.[Year]
FROM DW_PROD.dbo.Patient_Days_By_Month PD
LEFT JOIN [DW_PROD].[dbo].[DOTS_All] AMS
ON PD.Month_Name = AMS.Month
AND PD.Year = AMS.Year
AND [Medication Name] = 'CEFUROXIME'
GROUP BY
PD.[Patient Days],
PD.[Month_Name],
PD.[Fiscal_Month],
PD.[Accounting_Year],
PD.[Year]
ORDER BY
PD.ACCOUNTING_YEAR,
PD.FISCAL_MONTH
JOIN conditions do not need to refer to columns in other tables, they can as well contain constants.
The medication name was originally restricted in the WHERE clause - that eliminated all non-cefuroxime records from the resultset.