"with... as" in SQL Navigator - sql

The following query works:
select count(*) from everything where num not in (select num from sometable)
The following query is supposed to be equivalent to the above, but results in an "invalid identifier" error:
with unwanted as (select num from sometable)
select count(*) from everything where num not in unwanted
What is wrong with the second query?

the syntax is like this:
with unwanted as (select num from sometable)
select count(*) from everything where num not in (select * from unwanted)
obviously this makes only sense if the select num from sometable part is a bit more complex or used several times later...

You can also join the tables for faster performance
WITH unwanted
AS
(
SELECT num
FROM sometable
)
SELECT COUNT(*)
FROM everything a
LEFT JOIN unwanted b
ON a.num = b.num
WHERE b.num IS NULL

Related

Oracle 11G DB : Result from 'clob' type column in view changed while using the view in a where clause

I have the current query that i'm running in Oracle:
WITH viewa
AS (SELECT c.columna
FROM sometable c
LEFT JOIN othertable u
ON ( c.id = u.id )
WHERE id= '111'
ORDER BY c.created_date)
SELECT columna
FROM (SELECT rownum AS row_num,
t.*
FROM viewa t)
WHERE row_num > (SELECT CASE
WHEN ( Count(*) > 100 ) THEN Count(*) - 100
ELSE 0
END AS num
FROM viewa)
the idea is to always get the first 100 rows.
as you can see, i'm creating a view at the beginning and use it twice:
in the from and in the where.
i'm doing that so i wouldn't need to fetch the first select twice and it also make the query more readable.
notice that columna is of type CLOB!!
when i'm doing the same query with other column types its working!
so its probably something related to the clob column
The weird think is that the results that im getting are empty values even though i have values in the DB!
when i'm removing the subselect in the where i'm getting the right result:
WITH viewa
AS (SELECT c.columna
FROM sometable c
LEFT JOIN othertable u
ON ( c.id = u.id )
WHERE id = '111'
ORDER BY c.created_date)
SELECT columna
FROM (SELECT rownum AS row_num,
t.*
FROM viewa t)
WHERE row_num > 0
seems like Oracle is turning the values for the Clob column "columnA" into null when using the view in the where.
is someone familiar with that?
know how to go around it ?
i solved it with a different query but i still would like to know if Oracle does change the view while fetching from it?
thank you
Without sample data this is hard but I'm guessing the reason is you're depending on rownum. Use the FETCH clause instead to limit the number of rows.
WITH viewa
AS (SELECT c.columna
FROM sometable c
LEFT JOIN othertable u ON ( c.id = u.id )
-- an order by clause should go here
FETCH FIRST 100 ROWS ONLY)
SELECT columna
FROM viewa
But you don't need that CTE at all, just do
SELECT c.columna
FROM sometable c
LEFT JOIN othertable u ON ( c.id = u.id )
-- an order by clause should go here
FETCH FIRST 100 ROWS ONLY
Note that the "first" rows are not guaranteed to be a specific set of rows unless you explicitly add an ORDER BY clause.
Since 11g does not have FETCH FIRST, you can just use rownumber as the limiting criteria. See Example at Oracle Live
select columna, created_date
from (
select c.columna, c.created_date
from sometable c
left join othertable u
on ( c.id = u.id )
where c.id = '111'
order by c.created_date
)
where rownum <= 10;

PostgreSQL: Error in left join

I am trying to join my master table to some sub-tables in PostgreSQL in a single select query. I am getting a syntax error and I have the feeling I am making a terrible mistake or doing something which is not allowed. The code:
Select
id,
length,
other_stuff
from my_table tbl1
Left join
(
Select
id,
height
from my_table2 tbl2) tbl2 using (id)
left join
-- I get syntax error here
(
With a as (select id from some_table),
b as (Select value from other_table)
Select id, value from a, b) tbl3 using (id)
order by tbl1.id
Can we use WITH clause in left joins sub or nested queries and Is there a better way to do this?
UPDATE1
Well, I would like to add some more details. I have three select queries like this (having unique ID) and I want to join them based on ID.
Query1:
With a as (Select id, my_other records... from postgres_table1)
b as (select id, my_records... from postgres_table2)
c as (select id, my_record.. from postgres_table3, b)
Select
id,
my_records
from a left join c on some_condtion_with_a
order by 1
Second query:
Select
id, my_records
from
(
multiple_sub_queries_by_getting_records_from_c
)
Third Query:
With d as (select id, records.. from b),
e as (select id, records.. from d),
f as (select id, records.. from e)
select
id,
records..
from f
I tried to join them using left join. The first two queries were joined successfully. While, joining third query I got the syntax error. Maybe, I am complicating things thus I asked is there a better way to do it.
You are over complicating things. There is no need to use a derived table to outer join my_table2. And there is no need for a CTE plus a derived table to join the tbl3 alias:
Select id,
length,
other_stuff
from my_table tbl1
Left join my_table2 tbl2 using (id)
left join (
select st.id, ot.value
from some_table st
cross join other_table ot
) tbl3 using (id)
order by tbl1.id;
This assumes that the cross join you create with Select id, value from a, b is intended.
Not tested, but I think you need this. try:
with a as (select id from some_table),
b as (Select value from other_table)
Select
id,
length,
other_stuff
from my_table tbl1
Left join
(
Select
id,
height
from my_table2 tbl2
)
tbl2 using (id)
left join
(
Select id, value from a, b
)
tbl3 using (id)
order by tbl1.id
I've only ever seen/used WITH in the following format:
WITH
temptablename(columns) as (query),
temptablename2(columns) as (query),
...
temptablenameX(columns) as (query)
SELECT ...
i.e. they come first
You'll probably find it easier to write queries if you use indentation to describe nesting levels. I like to make my SELECT FROM WHERE GROUPBY ORDERBY at one indent level, and then tablename INNER JOIN ON etc more indented:
SELECT
column
FROM
table
INNER JOIN
(
SELECT subcolumn FROM subtable WHERE subclause
) myalias
ON
table.id = myalias.whatever
WHERE
blah
Organising your indents every time you nest down a layer really helps. By making everything that is "a table or a block of data like a table (i.e. a subquery)" indented the same amount you can easily see the notional order that the DB should retrieve
Move your WITHs to the top of the statement, you will still use the alias names in place in the sub sub query of course
Looking at your query, there isn't much point in your subqueries.. You don't do any grouping or particularly complex processing of the data, you just select an ID and another column and then join it in. Your query will be simpler if you don't do this:
SELECT
column
FROM
table
INNER JOIN
(
SELECT subcolumn FROM subtable WHERE subclause
) myalias
ON
table.id = myalias.whatever
WHERE
blah
Instead, do this:
SELECT
column
FROM
table
INNER JOIN
subtable
ON
table.id = subtable.id
WHERE
blah
Re your updated requirements, following the same pattern.
look for --my comments
With a as (Select id, my_other records... from postgres_table1)
b as (select id, my_records... from postgres_table2)
c as (select id, my_record.. from postgres_table3, b)
d as (select id, records.. from b),
e as (select id, records.. from d),
f as (select id, records.. from e)
SELECT * FROM
(
--your first
Select
id,
my_records
from a left join c on some_condtion_with_a
) Q1
LEFT OUTER JOIN
(
--your second
Select
id, my_records
from
(
multiple_sub_queries_by_getting_records_from_c
)
) Q2
ON Q1.XXXX = Q2.XXXX --fill this in !!!!!!!!!!!!!!!!!!!
LEFT OUTER JOIN
(
--your third
select
id,
records..
from f
) Q3
ON QX.XXXXX = Q3.XXXX --fill this in !!!!!!!!!!!!!!!!!!!
It'll work, but it might not be the prettiest or most necessary SQL arrangement. As both i and HWNN have said, you can rewrite a lot of these queries where you're just doing some simple selecting in your WITH.. But likely that theyre simple enough that the database optimizer can also see this and rerwite the query for you when it runs it
Just remember to code clearly, and lay your indentation out nicely to stop it tunring into a massive, unmaintainable, undebuggable spaghetti mess

Returning only duplicate rows from two tables

Every thread I've seen so far has been to check for duplicate rows and avoiding them. I'm trying to get a query to only return the duplicate rows. I thought it would be as simple as a subquery, but I was wrong. Then I tried the following:
SELECT * FROM a
WHERE EXISTS
(
SELECT * FROM b
WHERE b.id = a.id
)
Was a bust too. How do I return only the duplicate rows? I'm currently going through two tables, but I'm afraid there are a large amount of duplicates.
use this query, maybe is better if you check the relevant column.
SELECT * FROM a
INTERSECT
SELECT * FROM b
I am sure your posted code would work too like
SELECT * FROM a
WHERE EXISTS
(
SELECT 1 FROM b WHERE id = a.id
)
You can as well do a INNER JOIN like
SELECT a.* FROM a
JOIN b on a.id = b.id;
You can as well use a IN operator saying
SELECT * FROM a where id in (select id from b);
If none of them, then you can use UNION if both table satisfies the union restriction along with ROW_NUMBER() function like
SELECT * FROM (
SELECT *,
ROW_NUMBER() OVER(PARTITION BY id ORDER BY id) AS rn
FROM (
select * from a
union all
select * from b) xx ) yy
WHERE rn = 1;
Note: there's an ambiguity as to what you mean by a duplicate row, and whether you're talking about duplicate keys, or all fields being the same. My answer deals with all fields being the same; some of the others are assuming it's just the keys. It's unclear which you intend.
You might try
SELECT id, col1, col2 FROM a INNER JOIN b ON a.id = b.id
WHERE a.col1 = b.col1 AND a.col2 = b.col2
adding in other columns as necessary. The database engine should be intelligent enough to do the comparisons on the indexed columns first, so it'll be efficient as long as you don't have rows that are different only on lots of non-indexed fields. (If you do, then I don't think anything will do it particularly efficiently.)

Written a subquery that can return more than one field without using the Exists

The query below is supposed to pull records for fields with the max date.
I am getting an error
You have written a subquery that can return more than one field without using EXISTS reserved word in the Main query's FROM clause. Revise the SELECT statement of the subquery to request only one column.
Code:
SELECT *
FROM TableName
WHERE (((([Project_Name], [Date])) IN (SELECT Project_Name, MAX(Date)
FROM TableName
GROUP BY Project)));
Your probably thinking of a nested subquery used as a table, like the below:
select a.*, b.1, b.2
from FirstTable A
join (Select Id, firstcolumn as 1, secondcolumn as 2
from SecondTable) B on b.ID = a.ID
Works pretty much like a regular join except you are using a subquery. Hope that helps,
SELECT A.*
FROM TableName A
INNER JOIN (select Project_Name, max(Date) MaxDate
from TableName
group by Project) B
ON A.[Project_Name] = B.[Project_Name]
AND A.[Date] = B.MaxDate
A version using EXISTS() looks like this:
SELECT *
FROM TableName AS A
WHERE EXISTS(
SELECT * FROM (
SELECT B.Project_Name, MAX( B.Date ) AS MaxDate
FROM TableName AS B
GROUP BY B.Project_Name ) AS C
WHERE C.Project_Name = A.Project_Name AND C.MaxDate = A.Date
);
Although I have the feeling this will have poorer performance than a JOIN because the GROUP BY statement might have to be executed for each record and each call to the EXISTS() function...

ODBC Firebird Sql Query - Syntax

Trying to get an slightly more complex sql statement structured but can't seem to get the syntax right. Trying to select counts, of various columns, in two different tables.
SELECT
SUM(ColumninTable1),
SUM(Column2inTable1),
COUNT(DISTINCT(Column3inTable1))
FROM TABLE1
This works, however I can't for the life of me figure out how to add in a COUNT(DISTINCT(Column1inTable2) FROM TABLE2 with what syntax.
There are several solutions you can take:
Disjunct FULL OUTER JOIN
SELECT
SUM(MYTABLE.ID) as theSum,
COUNT(DISTINCT MYTABLE.SOMEVALUE) as theCount,
COUNT(DISTINCT MYOTHERTABLE.SOMEOTHERVALUE) as theOtherCount
FROM MYTABLE
FULL OUTER JOIN MYOTHERTABLE ON 1=0
UNION two queries and leave the column for the other table null
SELECT
MAX(theSum) as theSum,
MAX(theCount) as theCount,
MAX(theOtherCount) AS theOtherCount
FROM (
SELECT
SUM(ID) as theSum,
COUNT(DISTINCT SOMEVALUE) as theCount,
NULL as theOtherCount
FROM MYTABLE
UNION ALL
SELECT
NULL,
NULL,
COUNT(DISTINCT SOMEOTHERVALUE)
FROM MYOTHERTABLE
)
Query 'with a query per column' against a single record table (eg RDB$DATABASE)
SELECT
(SELECT SUM(ID) FROM MYTABLE) as theSum,
(SELECT COUNT(DISTINCT SOMEVALUE) FROM MYTABLE) as theCount,
(SELECT COUNT(DISTINCT SOMEOTHERVALUE) FROM MYOTHERTABLE) as theOtherCount
FROM RDB$DATABASE
CTE per table + cross join
WITH query1 AS (
SELECT
SUM(ID) as theSum,
COUNT(DISTINCT SOMEVALUE) as theCount
FROM MYTABLE
),
query2 AS (
SELECT
COUNT(DISTINCT SOMEOTHERVALUE) as theOtherCount
FROM MYOTHERTABLE
)
SELECT
query1.theSum,
query1.theCount,
query2.theOtherCount
FROM query1
CROSS JOIN query2
There are probably some more solutions. You might want to ask yourself if it is worth the effort of coming up with a (convoluted, hard to understand) single query to get this data were two queries are sufficient, easier to understand and in the case of large datasets: two separate queries might be faster.
In this case all "count" would return the same value.
Try to do the same using sub queries:
Select
(Select count (*) from Table1),
   (Select count (*) from table2)
from Table3