How can I get the distinct ids where ALL rows match a certain criteria in GBQ? - google-bigquery

I'm querying a database to get the distinct ids where all the rows with each id match the criteria. For example, I would like to query the table below to get the distinct id where all values are truue. In this case, I would only return a single row with the id of 1.
Column A
Column B
1
true
1
true
2
false
2
true
2
true
3
false
3
false
3
false
Expected result
ColumnA
1
Currently, I have a query such as this
select
columnA
from
table
group by
columnA
having
(count(columnB = false) = 0)
But I end up returning no data at all. Not an error, just nothing matching my query. This is an example with dummy data, but the actual DB is quite large so I would expect lots of data back.
Any help is appreciated!

consider to use LOGICAL_AND function.
WITH sample_table AS (
SELECT 1 column_a, true column_b UNION ALL
SELECT 1 column_a, true column_b UNION ALL
SELECT 2 column_a, false column_b UNION ALL
SELECT 2 column_a, true column_b UNION ALL
SELECT 2 column_a, true column_b UNION ALL
SELECT 3 column_a, false column_b UNION ALL
SELECT 3 column_a, false column_b UNION ALL
SELECT 3 column_a, false column_b
)
SELECT column_a
FROM sample_table
GROUP BY 1
HAVING LOGICAL_AND(column_b) IS TRUE;
+----------+
| column_a |
+----------+
| 1 |
+----------+

Related

Ger rows with 2 specifical occurrences

Column_A
Column_B
1
X
1
Z
2
X
2
Y
3
Y
4
X
4
Y
4
Z
5
Y
I want get all distinct values of Column A that has a row with Column B equal to X and other row with Column B equal to 'Y'
The result will be like this:
Column_A
1
4
I tried in this way:
SELECT DISTINCT COLUMN_A
FROM TABLE
INNER JOIN (
SELECT DISTINCT COLUMN_A
FROM TABLE
WHERE COLUMN_B = 'X') SUBTABLE
ON TABLE.COLUMN_A = SUBTABLE.COLUMN_A
WHERE TABLE.COLUMN_B = 'Y';
I think that this solution works but isn't optimum
Thanks a have a nice day
You can apply a simple aggregation by:
filtering only Column_B values you're interested in
aggregating for distinct values of Column_B
checking the amount of distinct values equals 2
SELECT Column_A
FROM tab
WHERE Column_B IN ('X', 'Y')
GROUP BY Column_A
HAVING COUNT(DISTINCT Column_B) = 2
or you can use the INTERSECT operator between:
the records having Column_B = 'X'
the records having Column_B = 'Y'
SELECT DISTINCT Column_A FROM tab WHERE Column_B = 'X'
INTERSECT
SELECT DISTINCT Column_A FROM tab WHERE Column_B = 'Y'
Check the demo here.

Always have SQL query return atleast one record

SELECT column_a,
CASE WHEN column_a > 10 THEN 0 ELSE 1 END AS column_b
FROM table_a;
This does not always returns record, my requirement is to always have at least 1 row returned.
Following a solution here I tried couple of workaround such as union but none of it works.
SELECT 2 as column_a,
CASE WHEN column_a > 10 THEN 0 ELSE 1 END AS column_b
FROM table_a
UNION
SELECT -1,-1 FROM table_a;
Is there a way I can make this query return a record even when none is found?
Well, query won't return anything if TABLE_A is empty (as there's no WHERE clause). In any other case, it'll return something.
Though, perhaps you meant to union it with a "dummy" select statement that selects from DUAL, not table_a (see line #6). Line #4 is here just to make the first select return no rows.
SQL> WITH table_a (column_a) AS (SELECT 3 FROM DUAL)
2 SELECT 2 AS column_a, CASE WHEN column_a > 10 THEN 0 ELSE 1 END AS column_b
3 FROM table_a
4 WHERE 1 = 2
5 UNION
6 SELECT -1, -1 FROM DUAL; --> DUAL here, not TABLE_A
COLUMN_A COLUMN_B
---------- ----------
-1 -1
SQL>
What is the problem you're trying to solve? Your title says "PL/SQL" which implies that this is happening in a PL/SQL block. In which case the standard answer would be just to catch the no_data_found exception and populate whatever variables you're fetching the data into with some appropriate default values.
BEGIN
SELECT column_a,
CASE WHEN column_a > 10 THEN 0 ELSE 1 END AS column_b
INTO local_variable1, local_variable2
FROM table_a;
EXCEPTION
WHEN no_data_found
THEN
local_variable1 := 1;
local_variable2 := -1;
END;
Likely, it would make sense to encapsulate this in a stored function.
If you really want to ensure that the query returns 1 row if there is no data in table_a, you could do something like this
SELECT column_a,
CASE WHEN column_a > 10 THEN 0 ELSE 1 END AS column_b
FROM table_a
UNION ALL
SELECT 1, -1
FROM dual
WHERE NOT EXISTS( SELECT 1 FROM table_a );
You can use:
SELECT *
FROM (
SELECT column_a,
CASE WHEN column_a > 10 THEN 0 ELSE 1 END AS column_b
FROM table_a
UNION ALL -- Use UNION ALL to keep duplicates from table_a.
SELECT -1,-1 FROM DUAL -- Use the DUAL table which always has exactly 1 row.
)
WHERE column_b >= 0 -- All the rows from table_a, if any exist.
OR ROWNUM = 1 -- Or, just the first row.
;
Which, for the empty table:
CREATE TABLE table_a (column_a INT);
Outputs:
COLUMN_A
COLUMN_B
-1
-1
And if you insert data:
INSERT INTO table_a (column_a)
SELECT 1 FROM DUAL UNION ALL
SELECT 2 FROM DUAL UNION ALL
SELECT 6 FROM DUAL UNION ALL
SELECT 10 FROM DUAL UNION ALL
SELECT 11 FROM DUAL UNION ALL
SELECT 11 FROM DUAL UNION ALL
SELECT 15 FROM DUAL;
Then the query outputs:
COLUMN_A
COLUMN_B
1
1
2
1
6
1
10
1
11
0
11
0
15
0
db<>fiddle here

How to guarantee a row if the query returns no rows?

I have the following union query:
select dataItem,1 as sortOrder from table1
union
select dataItem,2 from table2
order by sortOrder
If the first select query returns one row and the second select query returns no rows, then I get the following result:
dataItem | sortOrder
---------+----------
12345 | 1
I would like to make sure that there is always at least one row, so that if the seconde query returns no rows, we would have:
dataItem | sortOrder
---------+----------
12345 | 1
0 | 2
How can I make this happen?
The idea is to add union of max(dataItem) or 0 . Not sure on ACCESS syntax
select dataItem,1 as sortOrder from table1
union
select dataItem, 2 from table2
union
select iif(max(dataItem) is null, 0, max(dataItem)), 2 from table2
order by sortOrder
You can add one more union and this query checks if there is any row in table2, if no rows then return row with default values
select dataItem,1 as sortOrder from table1
union
select dataItem,2 from table2
union
select 0,2
where not exists (select 1 from table2)
order by sortOrder

SQL query how do I make sure only the criteria in a list are in a table

I am trying to do a query where I want to make sure only the criteria using the list related to the query are in the table.
here is an example table
table1
field1|field2
-------------
1 | 2
1 | 3
1 | 4
select * from table1
where field1 = 1
and field2 in(2,3)
This will return the first 2 records but what I want to do is to test and see if these are the only records where field1 is one. In this case I would want a query that would somehow return a false result to me.
So you want all field1 values that have a field2 value in (2,3) and no other values? Just add a NOT EXISTS:
select * from table1
where field1 = 1
and field2 in(2,3)
and NOT EXISTS
(
SELECT null
FROM table1
where field1 = 1
and field2 NOT in (2,3)
)
You could compare the overall count of rows where field1 is 1 and the count of the rows where field1 is 1 and field 2 is (2,3). If the values match then its TRUE else FALSE
Setup:
SELECT * INTO #TBLA FROM (
select 1 field1, 2 field2 UNION ALL
select 1 field1, 3 field2 UNION ALL
select 1 field1, 4 field2 ) A
Query:
SELECT CASE
WHEN COUNT(*) -
COUNT(CASE WHEN field2 IN (2,3)
THEN 1
END) > 0
THEN 'false'
ELSE 'true'
END FIELD1CNT
FROM #TBLA
WHERE field1 = 1

How can I obtain a transposed UNION of 3 SQL Tables?

How can I obtain a transposed UNION of the TSQL Query Results below
SELECT TOP 1 Column_A FROM table1
SELECT TOP 1 Column_B FROM table2
SELECT TOP 1 Column_C FROM table3
So that the output will be ONE row of 3 columns with a single value per each:
[Column_A] [Column_B] [Column_C]
Like this:
Select
(SELECT TOP 1 Column_A FROM table1) as 'Column_A',
(SELECT TOP 1 Column_B FROM table2) as 'Column_B',
(SELECT TOP 1 Column_C FROM table3) as 'Column_C'