I have run below select:
select replace(replace(id,'[',''),']','') as ID from tableA where COL1= 'TEST';
It returns 15 rows.
example of id:
1abc
3def
9abc
..
..
..
14abc
Then I'm looking this ID into other table:
select col1, col3 from tableB where
id in (select replace(replace(id,'[',''),']','') from tableA where COL1= 'TEST');
It returns 12 rows.
1abc city1
2def city2
5abc city2
.. ..
12abc city3
How to display missing 3 rows?
I suggest that there aren't actually any missing rows, but rather that 3 of the 15 rows returned by the first query are actually duplicate id values.
To see how this might work, consider that the first query returned the following 5 id values (for the sake of simplicity):
1
1
1
2
2
There are in fact 5 id values, but only 2 are actually unique. Then, the following WHERE clause:
WHERE id IN (1, 1, 1, 2, 2)
is equivalent to just saying:
WHERE id IN (1, 2)
Another possibility to this might be that tableB just does not contain every id returned by the first query.
To find the missing rows, here is one way:
WITH cte AS (
SELECT REPLACE(REPLACE(id, '[', ''), ']', '') AS ID
FROM tableA
WHERE COL1= 'TEST'
)
SELECT a.ID
FROM cte a
LEFT JOIN tableB b
ON a.ID = b.ID
WHERE b.ID IS NULL;
Related
I am new to sql and are trying to combine a column value from three different tables and combine to one row in DB2 Warehouse on Cloud. Each table consists of only one row and unique column name. So what I want to is just join these three to one row their original column names.
Each table is built from a statement that looks like this:
SELECT SUM(FUEL_TEMP.FUEL_MLAD_VALUE) AS FUEL
FROM
(SELECT ML_ANOMALY_DETECTION.MLAD_METRIC AS MLAD_METRIC, ML_ANOMALY_DETECTION.MLAD_VALUE AS FUEL_MLAD_VALUE, ML_ANOMALY_DETECTION.TAG_NAME AS TAG_NAME, ML_ANOMALY_DETECTION.DATETIME AS DATETIME, DATA_CONFIG.SYSTEM_NAME AS SYSTEM_NAME
FROM ML_ANOMALY_DETECTION
INNER JOIN DATA_CONFIG ON
(ML_ANOMALY_DETECTION.TAG_NAME =DATA_CONFIG.TAG_NAME AND
DATA_CONFIG.SYSTEM_NAME = 'FUEL')
WHERE ML_ANOMALY_DETECTION.MLAD_METRIC = 'IFOREST_SCORE'
AND ML_ANOMALY_DETECTION.DATETIME >= (CURRENT DATE - 9 DAYS)
ORDER BY DATETIME DESC)
AS FUEL_TEMP
I have tried JOIN, INNER JOIN, UNION/UNION ALL, but can't get it to work as it should. How can I do this?
Use a cross-join like this:
create table table1 (field1 char(10));
create table table2 (field2 char(10));
create table table3 (field3 char(10));
insert into table1 values('value1');
insert into table2 values('value2');
insert into table3 values('value3');
select *
from table1
cross join table2
cross join table3;
Result:
field1 field2 field3
---------- ---------- ----------
value1 value2 value3
A cross join joins all the rows on the left with all the rows on the right. You will end up with a product of rows (table1 rows x table2 rows x table3 rows). Since each table only has one row, you will get (1 x 1 x 1) = 1 row.
Using UNION should solve your problem. Something like this:
SELECT
WarehouseDB1.WarehouseID AS TheID,
'A' AS TheSystem,
WarehouseDB1.TheValue AS TheValue
FROM WarehouseDB1
UNION
SELECT
WarehouseDB2.WarehouseID AS TheID,
'B' AS TheSystem,
WarehouseDB2.TheValue AS TheValue
FROM WarehouseDB2
UNION
WarehouseDB3.WarehouseID AS TheID,
'C' AS TheSystem,
WarehouseDB3.TheValue AS TheValue
FROM WarehouseDB3
Ill adapt the code with your table names and rows if you tell me what they are. This kind of query would return something like the following:
TheID TheSystem TheValue
1 A 10
2 A 20
3 B 30
4 C 40
5 C 50
As long as your column names match in each query, you should get the desired results.
I have a table with following format and I want to get the LotId if Value1 is null for all the rows.
Now If I am doing Select,
Select * from Table1 where Value1 IS null , I am getting back a row .
But I want nothing should be returned as there are two rows which have some value.
I thought of self join , but this can have n number of rows.
Id LotId Value1
-------------------------------------------------
1 LOt0065 NULL
2 LOt0065 SomeValue
3 LOt0065 SomeValue
I think you'll need to use an EXISTS subquery here:
SELECT a.lotid
FROM table1 a
WHERE NOT EXISTS (
SELECT 1
FROM table1 b
WHERE b.lotid = a.lotid
AND b.value1 IS NOT NULL
);
If my syntax is right, then this will show you all records that don't have any NULL values for that lotid:
It uses a SELECT 1 because the subquery doesn't need to show any value, it just needs to match on the outer query.
You compare the table in the inner query to the table in the outer query and match on the common field you're looking at (lotid in this case)
This could also be done with a NOT IN clause.
Does this give you the result you want?
I have two tables table which are identical in structure but belong to different schemas (schemas A and B). All rows in question will always appear in the A.table but may or may not appear in B.table. B.table is essentially an override for the defaults in A.table.
As such my query uses a COALESCE on each field similar to:
SELECT COALESCE(B.id, A.id) as id,
COALESCE(B.foo, A.foo) as foo,
COALESCE(B.bar, A.bar) as bar
FROM A.table LEFT JOIN B.table ON (A.id = B.id)
WHERE A.id in (1, 2, 3)
This works great, but I also want to add the source of the data. In the example above, assuming id=2 existed in B.table but not 1 or 3, I would want to include some indication that A is the source for 1 and 3 and B is the source for 2.
So the data might look like the following
+---------------------------------+
| id | foo | bar | source |
+---------------------------------+
| 1 | a | b | A |
| 2 | c | d | B |
| 3 | e | f | A |
+---------------------------------+
I don't really care what the value of source is as long as I can distinguish A from B.
I am no pgsql expert (not by a long shot) but I have tinkered around with EXISTS and a subquery but have had no luck so far.
As records showing the default value (from A.table) have NULLs for B.id, all you need is to add this column specification to your query:
CASE WHEN B.id IS NULL THEN 'A' ELSE 'B' END AS Source
The USING clause would simplify the query you have:
SELECT id
, COALESCE(B.foo, A.foo) AS foo
, COALESCE(B.bar, A.bar) AS bar
, CASE WHEN b.id IS NULL THEN 'A' ELSE 'B' END AS source -- like #Terje provided
FROM a
LEFT JOIN b USING (id)
WHERE a.id IN (1, 2, 3);
But typically, this alternative query should serve you better:
SELECT x.* -- or list columns of your choice
FROM (VALUES (1), (2), (3)) t (id)
, LATERAL (
SELECT *, 'B' AS source FROM b WHERE id = t.id
UNION ALL
SELECT *, 'A' FROM a WHERE id = t.id
LIMIT 1
) x
ORDER BY x.id;
Advantages:
You don't have to add another COALESCE construct for every column you want to add to the result.
The same query works for any number of columns in a and b.
The query even works if the column names are not identical. Only number and data types of columns must match.
Of course, you can always list selected, compatible columns as well:
SELECT * -- or list columns of your choice
FROM (VALUES (1), (2), (3)) t (id)
, LATERAL (
SELECT foo, bar, 'B' AS source FROM b WHERE id = t.id
UNION ALL
SELECT foo2, bar17, 'A' FROM a WHERE id = t.id
LIMIT 1
) x
ORDER BY x.id;
The first SELECT determines names, data types and number of columns.
This query doesn't break if columns in b are not defined NOT NULL.
COALESCE cannot tell the difference between b.foo IS NULL and no row with matching id in b. So the source of any result column (except id) can still be 'A', even if the result row says 'B' - if any relevant column in b can be NULL.
My alternative returns all values from b if the row exists - including NULL values. So the result can be different if columns in b can be NULL. It depends on your requirements which behavior is desirable.
Either query assumes that id is defined as primary key (so exactly 1 or 0 rows per given id value).
Related:
Select first record if none match
What is the difference between LATERAL and a subquery in PostgreSQL?
Lets say I have a table with 2 columns (a, b) with following values:
a b
--- ---
1 5
1 NULL
2 NULL
2 NULL
3 NULL
My desired output:
a
---
2
3
I want to select only those distinct values from column a for which every single occurrence of this value has NULL in column b. Therefore from my desired output, "1" won't come in because there is a "5" in column b even though there is a NULL for the 2nd occurrence of "1".
How can I do this using a TSQL query?
If I understand correctly, you can do this with group by and having:
select a
from t
group by a
having count(b) = 0;
When you use count() with a column name, it counts the number of non-NULL values. Hence, if all values are NULL, then the value will be zero.
It's fairly simple to do:
SELECT A
FROM table1
GROUP BY A
HAVING COUNT(B) = 0
Grouping by A results in all the rows where the value of A is identical to be transferred into a single row in the output. Adding the HAVING clause enables to filter those grouped rows with an aggregate function. COUNT doesn't count NULL values, so when it's 0, there are no other values in B.
Two more ways to do this:
SELECT a
FROM t
EXCEPT
SELECT a
FROM t
WHERE b IS NOT NULL ;
This would use an index on (a, b):
SELECT a
FROM t
GROUP BY a
WHERE MIN(b) IS NOT NULL ;
Try it like this:
DECLARE #tbl TABLE(a INT, b INT);
INSERT INTO #tbl VALUES(1,5),(1,NULL),(2,NULL),(2,NULL),(3,NULL);
--Your test data
SELECT * FROM #tbl;
--And this is what you want - hopefully...
SELECT DISTINCT tbl.a
FROM #tbl AS tbl
WHERE NOT EXISTS(SELECT * FROM #tbl AS x WHERE x.a=tbl.a AND b IS NOT NULL)
To turn your question on it's head, you want the values from column a where there are no non-null values for that value in column b.
select distinct a
from table1 as t1
where 0 = (select count(*)
from table1 as t2
where t1.a = t2.a
and b is not null)
Sample fiddle is here: http://sqlfiddle.com/#!6/5d1b8/1
This should do it:
SELECT DISTINCT a
FROM t
WHERE b IS NULL
AND a NOT IN (SELECT a FROM t WHERE b IS NOT NULL);
I have a Table Like this:
TableA
----------------------------
ID - Name - PatID
1 A 10
2 B 10
3 A 11
4 A 12
5 B 13
I want to select All Such PatID Which has Name=A and Name = B.
So i should only get 10 as result.
What should be query for this?
You should be able to use the following query to get the result:
select patid
from tablea
where name in ('A', 'B')
group by patid
having count(distinct name) = 2;
See SQL Fiddle with Demo
If you need information from the A group and the B group you could also do it like this:
SELECT AGroup.ID AS AId, BGroup.ID AS BId
FROM TableA AGroup
JOIN TableB BGroup
ON AGroup.Name = 'A'
AND BGroup.Name = 'B'
AND AGroup.PatID = BGroup.PatID
This also retains duplicates if you have more than one entry, for Name = A and PatID = 10 for example.