I have a MariaDB database. I am running the With query.
when I run the below query its give me an error that the t1 table doesn't exist
with t1 as (select 't1'),
block1 as (
with inner1 as (
select * from t1
)
select * from inner1
),
block2 as (
with b2inner1 as(
select * from block1
),
b2inner2 as(
select * from block1
)
select * from b2inner2
)
select * from block2;
However, if I remove the block2 then the query works.
with t1 as (select 't1'),
block1 as (
with inner1 as (
select * from t1
)
select * from inner1
)
select * from block1;
My question is I haven't used t1 in the block2 subquery then why the query is giving the error.
I think the error occurring because I am selecting the result of the block1 twice in the block2 query. dbfiddle
Related
I have the following query that was given to me, where the returned record is removed from the table et_fact_reclam_ter_his_misc when the condition is met:
DELETE FROM et_fact_reclam_ter_his_misc
WHERE num_siniest || num_exped IN
(SELECT DISTINCT num_siniest || num_exped
FROM et_fact_reclam_ter_his_misc t1
WHERE NOT EXISTS (SELECT *
FROM et_fact_reclam_ter_misc t2
WHERE t1.num_siniest = t2.num_siniest));
I've been searching, and found that using EXISTS instead of IN will improve query performance. But I have run into 2 errors. The first is an error message that appears when I replace the IN operator with EXISTS:
DELETE FROM et_fact_reclam_ter_his_misc
WHERE num_siniest || num_exped EXISTS
(SELECT DISTINCT num_siniest || num_exped
FROM et_fact_reclam_ter_his_misc t1
WHERE NOT EXISTS (SELECT *
FROM et_fact_reclam_ter_misc t2
WHERE t1.num_siniest = t2.num_siniest));
ORA-00920: invalid relational operator
The second is when I try to nest a SELECT inside the DELETE, but the number of rows returned are different:
DELETE FROM et_fact_reclam_ter_his_misc
WHERE EXISTS
(SELECT FROM et_fact_reclam_ter_his_misc
WHERE num_siniest || num_exped IN
(SELECT DISTINCT num_siniest || num_exped
FROM et_fact_reclam_ter_his_misc t1
WHERE NOT EXISTS
(SELECT *
FROM et_fact_reclam_ter_misc t2
WHERE t1.num_siniest = t2.num_siniest)));
I appreciate any help to improve query performance
Could you try below, not the best approach to concatenate fields for joins,
DELETE FROM et_fact_reclam_ter_his_misc A
WHERE EXISTS
( SELECT 1 FROM
(SELECT DISTINCT num_siniest || num_exped
FROM et_fact_reclam_ter_his_misc t1) B
WHERE A.num_siniest|| A.num_exped = B.num_siniest || B.num_exped
AND NOT EXISTS (SELECT 1
FROM et_fact_reclam_ter_misc t2
WHERE B.num_siniest = t2.num_siniest));
Seems like the concatenated columns are numbers and it would force oracle to cast it to char which could hinder performance.Below one should be faster if you are dealing with lots of records.
DELETE FROM et_fact_reclam_ter_his_misc A
WHERE EXISTS
( SELECT 1 FROM
(SELECT DISTINCT num_siniest, num_exped
FROM et_fact_reclam_ter_his_misc t1) B
WHERE A.num_siniest = B.num_siniest
AND A.num_exped = B.num_exped
AND NOT EXISTS (SELECT 1
FROM et_fact_reclam_ter_misc t2
WHERE B.num_siniest = t2.num_siniest));
DISTINCT will overkill, substituting with group by will definitely be far better, so the best one will be :
DELETE FROM et_fact_reclam_ter_his_misc A
WHERE EXISTS
( SELECT 1 FROM
(SELECT num_siniest, num_exped,count(1)
FROM et_fact_reclam_ter_his_misc t1
group by num_siniest, num_exped) B
WHERE A.num_siniest = B.num_siniest
AND A.num_exped = B.num_exped
AND NOT EXISTS (SELECT 1
FROM et_fact_reclam_ter_misc t2
WHERE B.num_siniest = t2.num_siniest));
Looks like this might do it:
delete et_fact_reclam_ter_his_misc t1
where not exists
( select * from et_fact_reclam_ter_misc t2
where t2.num_siniest = t1.num_siniest
);
In the original version, the first level subquery seems to be querying the same table that is being deleted, just in order to construct a not exists subquery. I suspect that all you want to do is delete his rows where num_siniest does not exist in the main table. Some sample data and expected results would make this clearer.
I'm trying to write down a select to show me all the items that do not exist in my database. Say I have a table named TBL795 with a column named NRBEM which could not have any gaps in it.
Should be this way:
Those numbers are in sequence.
If they looked like this:
they would be wrong, because some items have not being inserted into the table.
In a table with thousand of items it would be very difficult to find out if there are any gaps and which are the missing items.
One solution would be this:
CREATE TABLE TESTE (
NRBEM VARCHAR(15))
feed it with a command like this:
INSERT INTO TESTE
WITH RECURSIVE
cnt(NRBEM) AS (VALUES(1) UNION ALL SELECT NRBEM+1 FROM cnt WHERE NRBEM <100000)
SELECT NRBEM FROM cnt A
and running this select
SELECT A.NRBEM FROM TESTE A LEFT JOIN TBL795 B
ON A.NRBEM = B.NRBEM
WHERE B.NRBEM IS NULL
I can see all the items that are missing in my table.
Since the command:
WITH RECURSIVE
cnt(NRBEM) AS (VALUES(1) UNION ALL SELECT NRBEM+1 FROM cnt WHERE NRBEM <100000)
SELECT NRBEM FROM cnt
create a virtual table I would like to run a select like this:
SELECT NRBEM FROM (
WITH RECURSIVE
cnt(NRBEM) AS (VALUES(1) UNION ALL SELECT NRBEM+1 FROM cnt WHERE NRBEM <100000)
SELECT NRBEM FROM cnt ) A LEFT JOIN TBL795 B
ON A.NRBEM = B.NRBEM
But this does not work.
This way:
SELECT X FROM (
WITH RECURSIVE
cnt(X) AS (VALUES(1) UNION ALL SELECT X+1 FROM cnt WHERE X <100000)
SELECT X FROM cnt ) A LEFT JOIN TBL795 B
ON A.X = B.NRBEM
it works, but does not select the right items.
So, how could I write this select?
It would be possible to use an outer join and filter out matches, but using set operations is simpler:
WITH RECURSIVE CNT(NRBEM) AS (...)
SELECT NRBEM
FROM CNT
WHERE NRBEM NOT IN (SELECT NRBEM
FROM tbl795);
I found out what I was doing wrong.
If I cast nrbem as number the select works.
SELECT A.X FROM (
WITH RECURSIVE
cnt(X) AS (VALUES(1) UNION ALL SELECT X+1 FROM cnt WHERE X <100000)
SELECT X FROM cnt ) A LEFT JOIN ( SELECT CAST( NRBEM AS NUMBER ) AS NRBEM FROM TBL795 ) B
ON A.X = B.NRBEM
WHERE B.NRBEM IS NULL
If I want to check the range from item 2400 to 2700 to see if there are any gaps I can do this:
SELECT A.X FROM (
WITH RECURSIVE
cnt(X) AS (VALUES(2400) UNION ALL SELECT X+1 FROM cnt WHERE X < (2700))
SELECT X FROM cnt ) A LEFT JOIN ( SELECT CAST( NRBEM AS NUMBER ) AS NRBEM FROM TBL795 WHERE NRBEM >= 2400 and nrbem <= 2700 ) B
ON A.X = B.NRBEM
WHERE B.NRBEM IS NULL
LIMIT ( 2700 - 2400 + 1 )
My tables are Store(ID, Name), Orders(ID, StoreID), OrderItem(ID, Quantity, OrderID, ProductID).
From the below code, i've got the Orders.ID when product 1 outsells product 2.
Now i need to refer to the store ID and get the name of the store. I'm stuck here.
When I try to add SELECT * FROM the below code, I got error ambiguous column name: OrderID.
What should I do?
SELECT OrderID as OID
FROM
(
SELECT *
FROM OrderItem as OI
WHERE OI.ProductID = 1
) AS A,
(
SELECT *
FROM OrderItem as OI
WHERE OI.ProductID = 2
) AS B
WHERE A.OrderID = B.OrderID AND A.Quantity > B.Quantity
The join you performed provides two tables A and B, both of them having the column OrderID, hence the SQL engine couldn't interpret which of the columns to display, thereby giving you the error. What you need to do is as follows:
SELECT A.OrderID as OID
FROM
(
SELECT *
FROM OrderItem as OI
WHERE OI.ProductID = 1
) AS A,
(
SELECT *
FROM OrderItem as OI
WHERE OI.ProductID = 2
) AS B
WHERE A.OrderID = B.OrderID AND A.Quantity > B.Quantity
When the column used for a join has the same name in both tables, you can use the USING clause, which not only saves typing, but also removes the duplicate column from the result:
SELECT OrderID as OID
FROM
(
SELECT *
FROM OrderItem as OI
WHERE OI.ProductID = 1
) AS A
JOIN
(
SELECT *
FROM OrderItem as OI
WHERE OI.ProductID = 2
) AS B
USING (OrderID)
WHERE A.Quantity > B.Quantity;
I would like to get all values in x that do not exists in table TableA.
I've tried following queries that is returning blank.
select x.num from
(
select '888888' as num from dual union all
select '111111' as num from dual
) x
left outer join TableA a on (a.number = x.num)
where a.number is null
select x.num
FROM
(
select '888888' as num from dual union all
select '111111' as num from dual
) x
where x.num not in
(
select a.number from TableA a where x.num = a.number
)
Table
| TableA.number |
-------------
111111
333333
The expected result is that only '888888' is returned in this case.
I can't see why this shouldn't work, where have i've done wrong?
Try this
with cte as
(
select '888888' as num from dual union all
select '111111' as num from dual
)
select cte.num
from cte
left join TableA a on (a.number = cte.num)
where a.number is null
I am new to the confusing pivot and unpivot operators available in Oracle. Can someone help me pivot the results of a query like this?
SELECT * FROM
(
SELECT
ROUND(((SELECT COUNT(*) FROM TABLE_X WHERE X = 1) / (SELECT (COUNT(*)) FROM TABLE_X) * 100))AS X_FIELD,
ROUND(((SELECT COUNT(*) FROM TABLE_Y WHERE Y = 1) / (SELECT (COUNT(*)) FROM TABLE_Y) * 100))AS Y_FIELD FROM DUAL
);
Results are something like this:
X_FIELD Y_FIELD
---------- ----------
37 26
And I need something like this:
FIELDS PERCENTAGE
---------- ----------
X_FIELD 37
Y_FIELD 26
Please guide me how to achieve this.
Try this:
WITH temp_result AS
(SELECT ROUND((
(SELECT COUNT(*) FROM TABLE_X WHERE X = 1) /(SELECT (COUNT(*)) FROM TABLE_X) * 100))AS X_FIELD,
ROUND(((SELECT COUNT(*) FROM TABLE_Y WHERE Y = 1) /(SELECT (COUNT(*)) FROM TABLE_Y) * 100))AS Y_FIELD
FROM DUAL
)
SELECT *
FROM temp_result UNPIVOT INCLUDE NULLS ( VALUE FOR COL IN (X_FIELD,Y_FIELD));