I have been using the following SQL:
SELECT DISTINCT NAME
FROM Events t1
LEFT JOIN UserHistory t2 ON t1.Name = t2.Event
WHERE t2.Event IS NULL
To select all rows from table 1 where table 2 is Null. This effectively filters out all my Table 1 data where Table 2 has data. However, I want to apply this only when a column in table 2 equals a certain value. Therefore I am looking to do a SELECT * FROM t2 WHERE t2.ID = 1 but am unsure how this fits into this query.
SELECT DISTINCT NAME
FROM Events t1
LEFT JOIN UserHistory t2 ON t1.Name = t2.Event and t2.certain_column = 1234
WHERE t2.Event IS NULL
Also you can try query with NOT EXISTS:
SELECT DISTINCT NAME
FROM Events t1
WHERE NOT EXISTS(SELECT * FROM UserHistory t2
WHERE t1.Name = t2.Event AND t2.ID = 1)
You need to add the predicate to the JOIN condition:
SELECT DISTINCT NAME
FROM Events t1
LEFT JOIN UserHistory t2 ON t1.Name = t2.Event AND t2.ID = 1
WHERE t2.Event IS NULL;
If you add it to the WHERE you effectively turn your outer join into an inner join, meaning no rows will be returned (since NULL = 1 evaluates to false)
Related
I have two table, t1 and t2.
-- t1
id name address
1 Tim A
2 Marta B
-- t2
id name address
1 Tim A
3 Katarina C
If I do t1 full outer join with t2
SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION ALL
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
However, the result has ambitious id, name, address.
How do I rename this so that I don't have duplicate column name?
Attempt:
SELECT name, address FROM
(SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION ALL
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id) as derived_table;
return: ERROR- duplicate column name "name".
Ditch the * in the SELECT list.
Specify the list of expressions to be returned. And qualify all column references with either the table name, or preferably, a shorter table alias.
And assign an alias to the expression and that will be the name of the column in the resultset.
Also, the query shown is not equivalent to a FULL OUTER JOIN.
If the goal is return all rows from t1, and to also return rows from t2 where a matching row doesn't exist in t1, I'd do something like this...
SELECT t.id AS t_id
, t.name AS t_name
, t.addr AS t_addr
FROM t1 t
UNION ALL
SELECT s.id
, s.name
, s.addr
FROM t2 s
LEFT
JOIN t1 r
ON r.id = s.id
WHERE r.id IS NULL
Try fully qualifying it like
SELECT t1.id, t1.name, t1.address FROM t1
I have two tables as such.
t1
id name
1 foo
2 bar
t2
tid id address
1 1 foss
I can execute select satement to select id 1 from t1 from both tables.
select * from t1 inner join t2 on (t1.id = 1 and t2.id = 1)
But, what I actually want is select bar from t1, and only bar, even though it isn't present in t2.
The above tables are similar to what I have been working on my project, and resembles to the same problem.
Here is what I tried.
1. I used left join t1.id = 2 and t2.id = 2
It lists all the values from t1, which I only wanted t1.id = 2.
2.inner join could be used, but since t2.id = 2 is not present.
Therefore, it doesn’t return anything.
But I wanted something that would display data from t1 and t2 if id is present in both tables, and if not display only from table t1 of only that id.
So, if I wanted to display t1.id = 2, the answer I would expect is using
select * from t1 join .....
id name tid id address
2 bar null null null
Based on your expected result this is a simple Left Join:
select *
from t1 left join t2
on t1.id = t2.id
where t1.id = 2
Use left join to get all elements of t1 even if a element of t2 with same id not exists.
Then use null to get only t1 when t2 not exists.
At last, you can add a where filter to get a subset of t1 (ie: id = 2)
SELECT t1.*, t2.*
FROM t1
LEFT JOIN t2
ON t1.id = t2.id
WHERE t2.id IS NULL
AND t1.id = 2;
Please consider this query:
SELECT table1.* ,
(SELECT quantity FROM table2 WHERE id = table1.id AND table2.location = 10) quantity,
(SELECT reorder_level FROM table2 WHERE id = table1.id AND table2.location = 10) reorder_level,
(SELECT stock_date FROM table2 WHERE id = table1.id AND table2.location = 10) stock_date
FROM table1
WHERE category_id = 5 ORDER BY table1.id;
The aliases quantity, location and stock_date are obviously referencing a a row in table2 that fulfill the condition: id=table1.id and location=10.
This query works, but is probably suboptimal as a result of the clumsy subqueries.
How can I best join table1 to table2 USING(id) but only on rows where location is also 10.
TIP: One row from table1 has many rows in table2.
Unfortunately, the actual table definitions are much more complex, and I reckoned it might be counter-productive to dump the entire thing on this thread.
You can use additional condition in ON() part so it will join only rows which fulfills the provided criteria
SELECT t1.* ,
t2.quantity ,
t2.reorder_level,
t2.stock_date
FROM table1 t1
LEFT JOIN table2 t2 ON t1.id = t2.id AND t2.location = 10
WHERE t1.category_id = 5
ORDER BY t1.id;
Another way would be use a subselect for your table2 and select only rows where location is equal to 10
SELECT t1.* ,
t2.quantity ,
t2.reorder_level,
t2.stock_date
FROM table1 t1
LEFT JOIN
(SELECT * FROM table2 WHERE t2.location = 10) t2
ON t1.id = t2.id
WHERE t1.category_id = 5
ORDER BY t1.id;
Ok. I have some data in one table, that references on multiple occasions some data in another table.
Table1 - main client table
Table2 - user defined fields
Say I have a query that shows a client id from Table1 and all attached / used "used defined fields" from Table2
SELECT t1.Id, t2.udf
FROM Table1 t1
JOIN Table2 t2 ON t1.Id = t2.Index
WHERE t1.EndDate IS NULL AND
t1.Id = '1234.9876' AND
I would get the following for a result...
ID UDF
1234.9876 100
1234.9876 110
1234.9876 118
1234.9876 124
1234.9876 198
1234.9876 256
Now, say I wanted to query this same thing, and get ONLY the ID of the Client, but ONLY IF a value for t2.udf equaling '194' did not exist. So, I would simply get
ID
1234.9876
...as a result.
Make the join a LEFT join and filer where t2.Index is null
SELECT t1.Id
FROM Table1 t1
LEFT JOIN Table2 t2 ON t1.Id = t2.Index
AND t2.UDF = 194 -- has to be before where clause
WHERE t2.Index IS NULL
AND t1.EndDate IS NULL
AND t1.Id = '1234.9876' -- not sure if you want this part
Another way by using NOT EXISTS
SELECT t1.Id
FROM Table1 t1
WHERE NOT EXISTS (SELECT 1 FROM Table2 t2 WHERE t1.Id = t2.INDEX
AND t2.UDF = 194)
AND t1.EndDate IS NULL
AND t1.Id = '1234.9876'
See also JOINS
You can add AND t2.udf not in (select udf from table2 where udf <> '194').
But #SQLMenace solution is better
This should do it.
SELECT DISTINCT t1.Id
FROM Table1 t1
LEFT JOIN Table2 t2 ON t1.Id = t2.Index
WHERE t2.UDF NOT IN (194)
AND t2.Index IS NULL
Select DISTINCT gives you unique entries that satisfy the other conditions, and the first where clause
t2.UDF NOT IN (194)
Normall would return all the rows for the t1 where the t2.UDF is not 194, but it is limited by the Select Distinct to give you only distinct id's
Try the following:
SELECT t1.Id
FROM Table1 t1
JOIN Table2 t2 ON t1.Id = t2.Index
WHERE t1.EndDate IS NULL AND
t1.Id = '1234.9876' AND
t2.udf <> '194'
SELECT
count(t1.id) AS c1
FROM
table2
LEFT JOIN table1 AS t1 ON (t1.uid = table2.uid)
WHERE
table2.mode = 'ls'
GROUP BY
t1.id
c1 = 6 -> CORRECT!
SELECT
count(t2.id) AS c2
FROM
table2
LEFT JOIN table1 AS t2 ON (t2.pid = table2.id)
WHERE
table2.mode = 'ls'
GROUP BY
t1.id
c2 = 1 -> CORRECT!
SELECT
count(t1.id) AS c1,
count(t2.id) AS c2
FROM
table2
LEFT JOIN table1 AS t1 ON (t1.uid = table2.uid)
LEFT JOIN table1 AS t2 ON (t2.pid = table2.id)
WHERE
table2.mode = 'ls'
GROUP BY
t1.id
c1 = 6 -> CORRECT!
c2 = 6 -> WRONG!
How do I request both counts in one query, without getting wrong results?
I need to count two different requests at the same table (table1).
so, I'm using an alias for both request. (t1). Each alias-request is working fine alone. If I use both in the same query, i got wrong results.
count() will get you the number of records that are returned by your query. Since if you removed the counts and replaced it with * you would have 6 rows both of those counts are giving you 6.
Is there any reason why you cant use two sub selects and return the result of each of those?
So:
SELECT subQ1.c1, subQ2.c2 FROM
(SELECT count(t1.id) AS c1 FROM table2
LEFT JOIN table1 AS t1 ON (t1.uid = table2.uid)
WHERE table2.mode = 'ls') as subQ1,
(SELECT count(t2.id) AS c2 FROM table2
LEFT JOIN table1 AS t2 ON (t2.pid = table2.id)
WHERE table2.mode = 'ls') as SubQ2;
I believe your problem on the full query is your group by function. You are grouping by t.id, thus a1.id will have a different count based on how many rows you have.
What I mean by this is if there are 6 rows in table t, then count is going to return 6 for table t; but also since there looks to be a 1 to 1 relation on table a, there are 6 matching rows in table a to the 6 matching rows in table t. such that
t.id = a.id
1 = 1
2= 2 ...etc.
Thus your count is returning rows versus the count you believe you should have? I believe sum function is what you want to use here.
You could try this...but I'm not really sure what you're trying to do.
SELECT (...)
count(CASE WHEN t1.uid = t3.uid THEN t1.id ELSE NULL END) AS CBanz,
count(CASE WHEN ta1.pid = t3.id THEN a1.id ELSE NULL END) AS CBanz1
FROM
t0
LEFT JOIN (...)
LEFT JOIN t1 ON (t1.uid = t3.uid)
LEFT JOIN t1 AS a1 ON (a1.pid = t3.id)
WHERE (...)