I have a simple table which has 4 fields:
indexID
UserID
text_1
IsFinal
This table may have multiple values for each UserID, and IsFinal field can have only a single value 1 or 0.
What I'm trying to do is to make a select statement which will return the user IDs if IsFinal only equal 0. The problem there may be multiple records for the same userID, some having IsFinal equal to 0 and only 1 with IsFinal equal to 1.
My problem here is this: for every UserID, if it has a record with Isfinal = 1, I want to ignore all records with the same UserID, otherwise I want to return its records. I don't know if that can be done by SQL statement only or not.
Seems like you want an anti-join, i.e. you first need to establish which user IDs have IsFinal = 1, then use that result set to return all user IDs not in that list.
There are various ways to implement an anti-join.
NOT IN:
SELECT *
FROM atable
WHERE UserID NOT IN (
SELECT UserID
FROM atable
WHERE IsFinal = 1
);
NOT EXISTS:
SELECT *
FROM atable t1
WHERE NOT EXISTS (
SELECT *
FROM atable t2
WHERE t1.UserID = t2.UserID
AND t2.IsFinal = 1
);
LEFT JOIN + WHERE IS NULL:
a)
SELECT *
FROM atable t1
LEFT JOIN (
SELECT *
FROM atable
WHERE IsFinal = 1
) t2 ON t1.UserID = t2.UserID
WHERE t2.UserID IS NULL;
b)
SELECT *
FROM atable t1
LEFT JOIN atable t2
ON t1.UserID = t2.UserID AND t2.IsFinal = 1
WHERE t2.UserID IS NULL;
It may so happen that they will be equally efficient in your database, but it still may be a good idea to test each of them to at least avoid ending up with one that performs worse than the others.
I think this is what you are looking for:
SELECT a.*
FROM translations a
INNER JOIN (SELECT UserID FROM translations WHERE IsFinal = 1) b
ON a.UserID = b.UserID
WHERE IsFinal = 0;
TRY ( not tested )
SELECT t1.* FROM table t1
INNER JOIN table t2 USING(indexID)
WHERE t1.IsFinal <>1
GROUP BY t1.UserID
Related
How can I write a query to give the results of three tables such that there's only one result per "line"?
The tables are:
T1 (ID, name, IP)
T2 (ID, date_joined)
T3 (ID, address, date_modified)
The relations are:
T1-T2 1:1, T1-T3 1:M - there can be many address rows per ID in T3.
What I want is a listing of all users with the fields above, but IF they have an address, I only want to record ONE (bonus would be if it is the latest one based on T3.date_modified).
So I should end up with exactly the number of records in T1 (happens to be equal to T2 in this case) and no more.
I tried:
select t.ID, t.name, t.IP, tt.ID, tt.date_joined, ttt.ID, ttt.address
from T1 t JOIN T2 tt ON (t.ID = tt.ID) JOIN T3 ttt ON (t.ID = ttt.ID)
And every sensible combination of LEFT, RIGHT, INNER, etc joins I could think of! I keep getting multiple duplicate because of T3
This query should work:
select
t1.ID, t1.name, t1.IP, t2.date_joined, t3x.address
from t1
join t2 on t1.ID = t2.id
left join (
select t3.*
from t3
join (
select id, max(date_modified) max_date
from t3
group by id
) max_t3 on t3.id = max_t3.id and t3.date_modified = max_t3.max_date
) t3x on t1.ID = t3x.id
First you do the normal join between t1 and t2 and then you left join with a derived table (t3x) that is the set of t3 rows having the latest date.
So T2 is actually not relevant here. You just need a way to join from T1 to T3 in a way that gets you at most one T3 row per T1 row.
One way of doing this would be:
select
T1.*,
(select address from T3 where T3.ID=T1.ID order by date_modified desc limit 1)
from T1;
This won't likely be very efficient, being a correlated subquery, but you may not care depending on the size of your dataset.
It's also only good for getting one column from T3, so if you had Address, City, and State, you'd have to figure out something else.
You can use sub query with Top 1 so that u get only one result from T3
here is a sample sql
select * into #T1 from(
select 1 ID
union select 2
union select 3) A
select * into #T2 from(
select 1 ID
union select 2
union select 3) A
select * into #T3 from(
select 1 ID, 'ABC' Address, getDate() dateModified
union select 1, 'DEF', getDate()
union select 3, 'GHI', getDate()) A
select *, (select top 1 Address from #T3 T3 where T3.ID= T1.ID order by datemodified desc) from #T1 T1
inner join #T2 T2 on T1.ID = T2.ID
Bonus :- you can also add order by dateModified desc to get the latest address
SELECT CI FROM users WHERE something;
IF users.CI='pc' THEN
SELECT name FROM table1 WHERE something;
ELSE IF users.CI='ph' THEN
SELECT name FROM table2 WHERE something;
END IF
I know that doesn't work, but is an example to understand.
It's possible all of this in one query ?
SET #var = (SELECT CI FROM users WHERE something);
SELECT
CASE #var
WHEN 'pc' THEN
(SELECT name FROM table1 WHERE something)
WHEN 'ph' THEN
(SELECT name FROM table2 WHERE something)
END;
You cannot use IF ... THEN in a SQL query.
The solution is to left outer join both tables, letting the optimizer choose which table will be used by specifying so in the ON clauses.
You didn't explain what "something" was, so in this example, I am going to assume that "users" has an "id" column and that table1 and table2 have a "user_id" column, and that you are interested in the user with id = 1.
SELECT COALESCE(t1.name,t2.name) AS name
FROM users u
LEFT JOIN table1 t1 ON u.CI = 'pc' AND t1.user_id = u.id
LEFT JOIN table2 t2 ON u.CI = 'ph' AND t2.user_id = u.id
WHERE u.id = 1;
I have 2 table table1 contains an userid and a postid. Table2 contains a userid and a username. I want to return all the userids with a certain postid and then use those userids to query table2 and get the usernames.
Is there a way to go about this? I have tried join statement and it doesn't seem to work
Use the IN function:
select username, userid from `table2` where userid in (select userid from `table` where postid = <condition>)
SELECT A.postid, A.userid, B.username FROM
tableA AS A JOIN tableB AS B ON A.userid=B.userid
select post id, user id from tableA username from tableB. Join these 2 different table columns when tableA's userid is equal to tableB's userid.
select t1.postid, t1.userid, t2.username
from table1 t2
left join table1 t2 on t1.userid = t2.userid
where t1.postid = <your postid>
Join the tables on the common columns
select t1.postid, t1.userid, t2.username
from table1 t1
join table2 t2 on t1.userid = t2.userid
where t1.postid = 2
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 (...)
I want to do a sql query and have some problems:
I want to select from table_1 the ID's Where parent_id is the value I have:
SELECT ID
FROM table_1
WHERE parent_ID = 'x'
I want to use the ID'S I got in 1. and
SELECT
FROM table_2
WHERE ID = 'The ID's from Query 1.'
Like this?
select ...
from table_1 a
join table_2 b on(a.id = b.id)
where a.parent_id = 'x';
Edit
Note: the query will potentially produce duplicate rows depending on the keys and relation between the tables. For example, you will get duplicates if, for a given table_1.parent_id = X, there can be multiple occurrences of the same table_1.ID.
Another example is when table_2.ID isn't unique.
In those cases you would want to remove the duplicates (using distinct, group by, partitioned #row_number, etc) or, not produce the duplicates in the first place using a semi-join instead (exists, in). Have a look #OMG Ponies answer for reference.
Using IN
SELECT t2.*
FROM TABLE_2 t2
WHERE t2.id IN (SELECT t1.id
FROM TABLE_1 t1
WHERE t1.parent_id = 'x')
Using EXISTS
SELECT t2.*
FROM TABLE_2 t2
WHERE EXISTS (SELECT NULL
FROM TABLE_1 t1
WHERE t1.id = t2.id
AND t1.parent_id = 'x')
Using an INNER JOIN
The DISTINCT (or GROUP BY) is necessary to eliminate duplicates if there are more than one records in TABLE_1 that relate to a record in TABLE_2:
SELECT DISTINCT t2.*
FROM TABLE_2 t2
JOIN TABLE_1 t1 ON t1.id = t2.id
AND t1.parent_id = 'x'
It can be solved with the use of IN as follows:
SELECT * FROM table_2 WHERE ID IN (SELECT ID FROM table_1 WHERE parent_ID = 'x')
select * from table_2 where id in (select id from table_1 where parent_id = 'x')
Yes, it's better to you use this:
SELECT [value]
FROM [table2]
WHERE [value] IN (SELECT [value]
FROM [table1]
WHERE [value] = "[value]"
)