Oracle - Check if there is a data in range of date - oracle

I have three tables (receipts, receiptaddinfo, shops). I have select, that gives me a data with a all receipts from all shops since the declared date:
select *
from receipts r
join receipt receiptaddinfo ri on r.receiptid=ri.receiptid and r.shop=ri.shop
join shops s on ri.shop=s.shop and shoptype=0
where ri.creationtime >= '2016-05-19 00:00:00'
order by ri.creationtime desc
The table shops, contain all shops, however, I want to check if there is a shop, which had no 'sale/receipts' since the declared date. Could somebody help?

You can try the following SQL statement.
SELECT * from shops s
WHERE s.shoptype = 0
AND NOT EXISTS
(SELECT 1
FROM receipts r,
receiptaddinfo ri
WHERE r.receiptid = ri.receiptid
AND r.shop = ri.shop
AND ri.shop = s.shop
AND ri.creationtime >= '2016-05-19 00:00:00')

Related

Update with count and group by expressions

First, I know there is a common issue in Stack Overflow, but the following solutions are not working well here. So I still need some help.
Oracle - Update COUNT of rows with specific value
Oracle - Update rows with a min value in the group of a column from another table
Oracle update statement with group function
Oracle - Update COUNT of rows with specific value
The problem is: I have a +700k lines table:
REVIEWS (PRODUCT_ID, REVIEW, REVIEW_DATE, RELEASE_DATE, ..., REVIEW_COUNT)
I'm trying to update REVIEW_COUNT by counting the lines with the same PRODUCT_ID (I want just reviews before product release). So the code below works very well for my purpose:
SELECT COUNT(PRODUCT_ID) FROM REVIEWS
WHERE REVIEW_DATE < RELEASE_DATE
GROUP BY PRODUCT_ID
But I'm having a hard time to do the update. First I tried this:
UPDATE REVIEWS R
SET R.REVIEWS_COUNT =
(SELECT COUNT(RR.PRODUCT_ID) FROM REVIEWS RR
WHERE RR.DATA < RR.REL_DATE
GROUP BY RR.PRODUCT_ID)
The error is "more than one row", which is not surprising, but since I'm using the group by statement, it shouldn't occur. So I tried a self-join:
UPDATE REVIEWS R
SET R.REVIEWS_COUNT =
(SELECT COUNT(RR.PRODUCT_ID) FROM REVIEWS RR
WHERE RR.PRODUCT_ID = R.PRODUCT_ID AND RR.DATA < RR.REL_DATE)
But the query is taking forever and I don't think that should take so long, the simple select is pretty normal-fast.
I've also tested some more fancy and more simple stuff, but the outcome remains the same: long time waiting and it seems just wrong.
Please, what I'm missing in such easy update?
Maybe instead of updating you could define view:
select product_id, review_date, release_date,
count(case when review_date < release_date then 1 end)
over (partition by product_id) review_count
from reviews;
You could also try merge instead update:
merge into reviews a
using (select product_id, count(product_id) cnt from reviews
where review_date < release_date
group by product_id ) b
on (a.product_id = b.product_id)
when matched then update set reviews_count = b.cnt
dbfiddle
I think your second update is correct:
UPDATE REVIEWS R
SET R.REVIEWS_COUNT =
(SELECT COUNT(RR.PRODUCT_ID) FROM REVIEWS RR
WHERE RR.PRODUCT_ID = R.PRODUCT_ID AND RR.DATA < RR.REL_DATE)
;
This will update every record in the reviews table. Is that what you wanted?
An index on product_id will make the inner query run faster, but it will still update all 700K or so records.

MAX DATE with Multiple tables/Inner Joins in Toad/Oracle

I have only been using Toad/Oracle for a few weeks so am still learning coding etc I have knowledge of SQL Code in Access and trying to now learn Oracle.
I need to return the max date from UCMRBILDAT from tbl BIC/AZUCDMO0100 but only from contracts which are contained in linked tbl LH_DAT
I have also tried a having MAX UCMRBILDAT but this didnt work.
UCMRBILDAT (/BIC/AZUCDMO0100)
UC_MRESULT (/BIC/AZUCDMO0100)
UC_MRSTAT (/BIC/AZUCDMO0100
UC_MRCAT (/BIC/AZUCDMO0100)
CONTRACT_NUMBER (LH_DAT)
UC_MR_NUMB (/BIC/AZUCDMO0100) + (/BIC/AZUCDMO0200)
SELECT UCMRBILDAT,
UC_MRESULT,
UC_MRSTAT,
UC_MRCAT
FROM LH_DAT
( SELECT CONTRACT_NUMBER, MAX (UCMRBILDAT) MXBD
FROM SAPSR3."/BIC/AZUCDMO0100"
GROUP BY CONTRACT_NUMBER) GMR
LEFT OUTER JOIN SAPSR3."/BIC/AZUCDMO0200"
ON (CONTRACT_NUMBER = UCCONTRACT)
INNER JOIN SAPSR3."/BIC/AZUCDMO0100"
ON ("/BIC/AZUCDMO0200".UC_MR_NUMB = "/BIC/AZUCDMO0100".UC_MR_NUMB)
WHERE CONTRACT_NUMBER = '2000014420'
AND UCMRBILDAT = MXBD
AND MR.CONTRACT_NUMBER = GMR.CONTRACT_NUMBER
Max bill date from BIC/AZUCDMO0100 but only for contracts contained in table LH_DAT
EDIT NEED MAX DATE FOR UCMRBILDAT ON BELOW SCRIPT
SELECT CONTRACT_NUMBER,
UCMRBILDAT,
UC_MRESULT,
UC_MRCAT
FROM LH_DAT
LEFT OUTER JOIN SAPSR3."/BIC/AZUCDMO0200"
ON (CONTRACT_NUMBER = UCCONTRACT)
INNER JOIN SAPSR3."/BIC/AZUCDMO0100"
ON ("/BIC/AZUCDMO0200".UC_MR_NUMB = "/BIC/AZUCDMO0100".UC_MR_NUMB)
WHERE CONTRACT_NUMBER = '2000014420'
AND "/BIC/AZUCDMO0200".SOURSYSTEM = 'SP'
AND "/BIC/AZUCDMO0200".UCDELE_IND <> 'X'
To get the max value of "BIC/AZUCDMO0100".UCMRBILDAT where there's a linked value from LH_DAT you'd want to use:
SELECT MAX(ba.UCMRBILDAT)
FROM SAPSR3."BIC/AZUCDMO0100" ba
INNER JOIN LH_DAT ld
ON ld.some_field = ba.some_field
There must be fields which link "BIC/AZUCDMO0100" and LH_DAT together, but in your query they're not specified. Find those fields, plug them in to the query above, and you should get the result you're looking for.

SQL query multiple joins not working

I am using oracle database and trying to run the following query but it gives the error:
"ERROR at line 17: ORA-00904: "FRH"."NS": invalid identifier"
What is the problem with it?
Following is the query:
SELECT *
FROM
(SELECT *
FROM ROOMS R
WHERE R.Prix<'50') FRM
JOIN
(SELECT *
FROM
(SELECT *
FROM HOTELS H
WHERE H.CatH=2) FH
JOIN
(SELECT *
FROM RESORTS R
WHERE TypeS='montagne') FR
ON FH.NS=FR.NS) FRH
ON (FRH.NS=FRM.NS AND FRH.NH=FRM.NH);
Thanks in advance
You have way too many nested selects here. Your query can be simplified to:
SELECT *
FROM rooms rm
JOIN hotels ht ON ht.ns = rm.ns AND ht.nh = rm.nh
JOIN resorts rs ON rs.ns = ht.ns
WHERE rm.prix < 50
AND ht.cath = 2
AND ss.types = 'montagne';
I am not entirely sure which tables need to be joined using just the ns column and which need both the ns and nh column because you have obfuscated your query so much and did not show us the table definitions.
Alternatively you can move the restrictions on the joined tables into the join condition. This isn't necessary for the inner joins you are using, but could be needed if you ever want to change that to an outer join:
SELECT *
FROM rooms rm
JOIN hotels ht ON ht.ns = rm.ns AND ht.nh = rm.nh AND ht.cath = 2
JOIN resorts rs ON rs.ns = ht.ns AND rs.types = 'montagne'
WHERE rm.prix < 50;
You should also not compare numbers and strings. Assuming rooms.prix is a number column, the condition R.Prix<'50' is wrong. You need to compare the number to a number r.prix < 50

Query to get list of Inventory Items for which there is no material transaction in Oracle

Have a small doubt I want to compile a SQL query in Inventory where I have to get those Items for which transactions have not been recorded during a period of at least a specified number of days.
The days could be 30 days or 2 months depends. So I want to get those items for which no transaction was recorded for lets say 30 days. Could anyone give me an idea of how to go about this thing?? I am using r12. I came up with the following query but it is giving many records. The commented portions of this query remains commented only
select distinct msi.segment1, msi.description, msi.primary_uom_code,
msi.inventory_item_id
from mtl_system_items_b msi /*,
mtl_material_transactions mmt*/
where /*msi.inventory_item_id = mmt.inventory_item_id
AND msi.organization_id = mmt.organization_id
AND NVL((SELECT SUM(transaction_quantity)
FROM mtl_onhand_quantities
WHERE inventory_item_id = msi.inventory_item_id),
0) = 0
AND TRUNC(mmt.transaction_date) <= SYSDATE - &D
AND*/
not exists
(select *
from mtl_material_transactions mmt
where msi.inventory_item_id = mmt.inventory_item_id
and msi.organization_id = mmt.organization_id
and trunc(mmt.transaction_date) < sysdate - &D)
Here is a variation of your query that will give all items with on hand inventory that have not been transacted in a determined number of days.
select distinct msi.segment1
,msi.description
,msi.primary_uom_code
--,msi.inventory_item_id
,q.organization_id
,q.quantity
from mtl_system_items_b msi
join (SELECT inventory_item_id, organization_id, SUM(transaction_quantity) quantity
FROM mtl_onhand_quantities
GROUP BY inventory_item_id, organization_id) q on msi.inventory_item_id = q.inventory_item_id and msi.organization_id=q.organization_id
where not exists (select *
from mtl_material_transactions mmt
where msi.inventory_item_id = mmt.inventory_item_id
and msi.organization_id = mmt.organization_id
and trunc(mmt.transaction_date) > sysdate - 180)
order by q.organization_id,msi.segment1;

Display only the largest count in a group by statment

I'm trying to display only the largest group in this group by statement;
SELECT COUNT(type) AS booking, type FROM booking b, room r WHERE r.rno = b.rno AND r.hno = b.hno GROUP BY type;
I modified it so we get this query response now you can see group double is larger then family.
BOOKING TYPE
5 double
2 family
I know there is a HAVING keyword you can add in order display only a count compared to a number so I could do COUNT(type) HAVING > 2 or similar but that's not very dynamic and that would only work in this instance because I know the two amounts.
ORDER BY COUNT(type) DESC LIMIT 1
There isn't a having statement that does this. But you can use rownum with a subquery:
select t.*
from (SELECT COUNT(type) AS booking, type
FROM booking b join
room r
on r.rno = b.rno AND r.hno = b.hno
GROUP BY type
order by count(type) desc
) t
where rownum = 1;
Just order your query..
order by booking desc
regards
TRY this
SELECT COUNT(type) AS booking, type FROM booking b, room r WHERE r.rno = b.rno AND r.hno = b.hno ORDER BY type DESC LIMIT 1

Resources