Why does this sql snippet return 8 or 1 always? - sql

What is the result of:
WITH Tbl AS (SELECT 5 AS A UNION SELECT 6 AS A)
SELECT COUNT(*) AS Tbl FROM Tbl AS A, Tbl AS B, Tbl AS C;
I know the result is supposed to be 8 but I don't know why. Also when I change both values (the 5 or 6) to the same thing it returns a table with the value 1 instead of 8 but all other instances it returns 8 no matter what numbers if they are different. I tested it out with an online sql executor.

Here is what the query does:
the common table expression (the subquery within the with clause) generates a derived table made of two rows
then, in the outer query, the from clause generates a cartesian product of this resultset twice: that's a total of 8 rows (2 * 2 * 2)
the select clause counts the number of rows - that's 8
The content of the rows in the with clause does not matter: this 5 and 6 could very well be foo and bar, or null and null, the result would be the same.
What makes a difference is the number of rows that the with clause generates. If it was generating just one row, you would get 1 as a result (1 * 1 * 1). If it was generating 3 rows, you would get 27 - and so on.

This expression:
WITH Tbl AS (SELECT 5 AS A UNION SELECT 6 AS A)
creates a (derived) table with two rows.
This expression:
WITH Tbl AS (SELECT 5 AS A UNION SELECT 5 AS A)
creates a (derived) table with one row, because UNION removes duplicates.
The rest of the query just counts the number of rows in the 3-way Cartesian product, which is either 111 or 222.

Related

How to take MAX from column values in SparkSQL

I have a use case where I need to take max value from different columns from a table in sparksql.
Below is a sample table -
I want to take the max of values from columns a, b and c without using the union clause.
Below is the SL query I executed -
SELECT (
SELECT MAX(myval)
FROM (VALUES (a),(b),(c)) AS temp(myval)
) AS MaxOfColumns
FROM
table
But this is throwing an error - "cannot evaluate expression outer() in inline table definition; line 3 pos 16"
Could you please help me with this?
array_max
with t(id,a,b,c) as (select stack(2 ,100,1,2,3 ,200,5,6,4))
select *, array_max(array(a,b,c)) as MaxOfColumns
from t
id
a
b
c
MaxOfColumns
100
1
2
3
3
200
5
6
4
6

Execute both the query and the COUNT of the query

I'm trying to build a query or a PL/SQL code to both execute a query, as well as return the number of results of this query.
Is this possible in a single query? Right now I feel like I'm being very wasteful: I first wrap the query in a COUNT (without ORDER BY) and then run the same query again (without the COUNT). A difference of a few seconds will probably not change the total number of rows, I can live with that.
The DB I'm using is Oracle Enterprise 12.2
An easy SQL way:
a test table:
create table testTable(a, b, c) as (
select 1, 'one', 'XX' from dual UNION ALL
select 2, 'two', 'YY' from dual UNION ALL
select 3, 'three', 'ZZ' from dual
)
A simple query:
select a, b, c
from testTable
A B C
---------- ----- --
1 one XX
2 two YY
3 three ZZ
3 rows selected.
The query with the number of records :
select a, b, c, count(*) over (partition by 1) as count
from testTable
A B C COUNT
---------- ----- -- ----------
1 one XX 3
2 two YY 3
3 three ZZ 3
3 rows selected.
You can try to do something like:
WITH test_query
AS (SELECT LEVEL just_a_number
FROM dual
CONNECT BY level < 101)
SELECT just_a_number
, COUNT(just_a_number) OVER (ORDER BY 1) total_count
FROM test_query;
Where COUNT(just_a_number) OVER (ORDER BY 1) will return total number of rows fetched in each row. Note that it may slow down the query.
Typically, when I do something like this, I create a stored procedure that returns 2 values. The first would be the result set as a REF CURSOR, and the other a number(12,0) returning the count. Both would of course require separate queries, but since it is in a single stored procedure, it is only one database connection and command being executed.
You are of course right for having your COUNT query forgo the ORDER BY clause.
To answer your question, you are not being wasteful per se. This is common practice in enterprise software.

Select postgresql for combinations

I have the following 2 tables:
SQL Tables
I have a list of ids (1,2,3,4,5,6,7,8, ..., 10000).
Unique combination of those ids is inserted into another table.
So, how can I find these inique combination If I pass the list of ids to search.
E.g., I search for ARRAY([2,3,4]). The combination exisst only for the unique_combnation 1, so the result will be as follows:
1 3
1 2
1 4
There is no any unique_comb which contains ids ARRAY([2,3,4]).
If I search for [1,4], the results will be as follows:
1 3
1 2
1 4
2 2
2 4
2 5
How can I do it? I know how to do it in a bad way:
CREATE TEMPORARY TABLE t1
Iterate over given ids: SELECT * FROM .. where id = ANY(ARRAY[1,4]) and get all rows, insert into t1 all rows.
Then group everything by unique_comb.
Then count the number of groups. If the number of unique combinations is not more than 1, then return the id of the unique combination, else (unique combinations > 1) return nothing
Is it a way to make it with 1-2 sql lines? I am using postgresql 9.3
select unique_comb t2 where id = ANY(ARRAY[1, 4]) group by unique_comb ...
The answer below is correct. I have modifed just a little bit the query and it began to work.
It will choose several ids from table unique thing.
The result will be of select unique_comb, array_agg(id) t2 where id = ANY(ARRAY[1, 4]) group by unique_comb will be as follows:
The process that you describe is seems to be something like a group by:
select unique_comb
from t2
where id = ANY(ARRAY[1, 4])
group by unique_comb
having count(*) = array_length(ARRAY[1, 4], 1);
For big tables, and long arrays (not for your examples with just 2 or 3 elements), a more sophisticated query with a recursive CTE would be faster.
In any case you need an index on (id, unique_comb) - in this order! A primary key serves nicely.
WITH RECURSIVE cte AS (
SELECT unique_comb, id, 2 AS i -- start with index for 2nd array elem
FROM tbl
WHERE id = 5 -- *first* element array
UNION ALL
SELECT t.unique_comb, t.id, c.i + 1
FROM cte c
JOIN tbl t USING (unique_comb)
WHERE t.id = ('{5, ... long array ... , 4}'::int[])[c.i] -- your array here
)
SELECT unique_comb
FROM cte
WHERE id = 4; -- *last* element of array
The advantage of this approach is to rule out most (or all) rows early in the game. If you have information on value frequencies, you would put the rarest elements first.

columns to rows change in oracle sql

I have columns a,b in table x.And i want to change this columns data into rows.
it is possible to have duplicate vales in table but in columns to row change only distinct values should come.
E.G:
a b
1 2
1 11
3 4
5 6
7 8
9 10
......etc
the result 1 (query 1) should be 1-2,1-11,3-4,5-6,7-8,9-10.....etc
The result 2 (query 2) should b 1,3,5,7,9....etc(only one 1 must come as we have duplicate data for column a)
how can i achieve this in oracle SQL.
Please help.
For Oracle 11 use function listagg() and in first query concatenate columns, in second - select distinct values at first.
Query 1:
select listagg(a||'-'||b, ',') within group (order by a, b) result from t
RESULT
------------------------------
1-2,1-11,3-4,5-6,7-8,9-10
Query 2:
select listagg(a, ',') within group (order by a) result
from (select distinct a from t)
RESULT
------------------------------
1,3,5,7,9
For older versions you can use wmsys.wm_concat.

SQL Query to find which group does not have a given value

I am using T-SQL.
Say if I have the following
Value Nbr
----- ---
one 6
one 7
one 8
two 6
two 7
three 5
three 3
three 2
In the above table, I need to find which group does not have 6 in it.
In this case, it is three as it does not have 6 in it.
What would be the best approach to do this?
I tried:
select Value from tbl1
where nbr <> 6
group by Value
but did not get the intended result.
select distinct value
from tbl1
where value not in
(
select distinct value
from tbl1
where nbr = 6
)