I'm trying to select a bunch of rows from my first table depending of values from my second table.
To realize that, I came up with the following query :
SELECT *
FROM table2 t2
WHERE t2.id IN(
SELECT subquery.id
FROM
(
SELECT id
FROM table1 t1
WHERE (t1.property=10 AND t1.value=0)
) AS subquery
INNER JOIN
(
SELECT id
FROM table1 t1
WHERE (t1.property=20 AND i.value=1)
) AS subquery2
on subquery.id=subquery2.id
)
Depending of the property and value from table1, a specific list of id will be selected to be used as a condition for the final SELECT with the table2.
The subquery in itself is working, I tested it and I could retrieve the good id.
+------+
| id |
|------|
| 18 |
| 55 |
¦ ¦
Problem is, the IN isn't working, at the end of the final SELECT I retrieved all the rows from table2 instead of the ones respecting the condition of having the same id as the subquery retrieved earlier.
+------+------+---
| id | name |
|------|------|---
| 1 | xx |
| 2 | yy |
¦ ¦ ¦
So my question is :
Why is the subquery ignored in my IN statement and is there a way to bypass that problem ?
EDIT
Here is a SQLFiddle as requested, but strangely, the code I posted is working here but not for my database.
SELECT * FROM table2 t2
INNER JOIN
(SELECT
subquery.id
FROM
(SELECT
id
FROM
table1 t1
WHERE
(t1.property = 10 AND t1.value = 0)) AS subquery
INNER JOIN
(SELECT
id
FROM
table1 t1
WHERE
(t1.property = 20 AND i.value = 1)) AS subquery2 ON subquery.id = subquery2.id)Z ON Z.id=t2.id
You can try above code.
Hope this will help.
try like the following; if you are having any null values in the columnn you won't get the expected result.
common_id not in
(
select common_id from Table1
where common_id is not null
)
SQL "select where not in subquery" returns no results
Related
table one
+----------------------+
|column A | Column B|
| 2 | 4 |
| 3 | 5 |
| 1 | 2 |
| 1 | 2 |
| 8 | 7 |
+----------------------+
Output
+-------+
|1 | 2 |
|1 | 2 |
+-------+
i want to print only the above output without COUNT, and any duplicate record example? please help
how about below where cluase
select * from t where columnA=1 and columnB=2
or
select columnA,columnB from t
group by columnA,columnB
having count(*)>1
or you can use exists
select t1.* from t t1 where exists
(select 1 from t t2 where t2.columnA=t1.columnA
and t2.columnB=t1.columnB group by columnA,columnB
having count(*)>1
)
You possibly want only those rows which are duplicate. If you don't have Window Functions available in your MySQL version, you can do the following:
SELECT
t.*
FROM your_table AS t
JOIN (SELECT columnA, columnB
FROM your_table
GROUP BY columnA, columnB
HAVING COUNT(*) > 1) AS dt
ON dt.columnA = t.columnA AND dt.columnB = t.columnB
Details: In a Derived table, we get all those combination of columnA and columnB which have more than one row(s) (HAVING COUNT(*) > 1).
Now, we simply join this result-set back to the main table, to get those rows only.
Note: This approach would not be needed if you want to fetch only these two columns. A simple Group By with Having would suffice, as suggested in other answer(s). However, if you have more columns in the table, and you will need to fetch all of them, and not just the columns (used to determine duplicates); you will need to use this approach.
You can use in operator with a grouped subquery as :
select *
from tab
where ( columnA, columnB) in
(
select columnA, count(columnA)
from tab
group by columnA
);
or use a self-join as :
select t1.columnA, t1.columnB
from tab t1
join
(
select columnA, count(columnA) as columnB
from tab
group by columnA
) t2
on ( t1.columnA = t2.columnA and t1.columnB = t2.columnB );
Rextester Demo
I would use EXISTS, if the table has primary column :
SELECT t.*
FROM table t
WHERE EXISTS (SELECT 1 FROM table t1 WHERE t1.col1 = t.col1 AND t1.col2 = t.col2 AND t1.pk <> t.pk);
I have a table like this in MYSQL:
ID | NAME | VALUE |
----------------------------
1 | Bob | 1 |
2 | Bob | 2 |
3 | Jack | 5 |
4 | Jack | 8 |
5 | Jack | 10 |
and I'm trying to update the VALUE column to the highest value of rows with same NAME. So the result should be:
ID | NAME | VALUE |
----------------------------
1 | Bob | 2 |
2 | Bob | 2 |
3 | Jack | 10 |
4 | Jack | 10 |
5 | Jack | 10 |
I managed to get the max value like this:
SELECT MAX(Value) max FROM `table` GROUP BY Name having count(*) >1 AND MAX(Value) != MIN(Value)
But can't figure out how to put it in my update
Update table set Value = (SELECT MAX(Value) max FROM `table` GROUP BY Name having count(*) >1 AND MAX(Value) != MIN(Value))
Doesn't work. I'd appreciate any help.
This is easier than other answers are making it.
UPDATE MyTable AS t1 INNER JOIN MyTable AS t2 USING (Name)
SET Value = GREATEST(t1.Value, t2.Value);
You don't have to find the largest value. You just have to join each row to the set of rows with the same name, and set the Value to the greater Value of the two joined rows. This is a no-op on some rows, but it will apply to every row in turn.
http://sqlfiddle.com/#!9/f79a3/1
UPDATE t1
INNER JOIN (SELECT name, MAX(`value`) max_value
FROM t1 GROUP BY name) t2
ON t1.name = t2.name
SET t1.value = t2.max_value;
Create a temporary table consisting of ID NAME and MAX VALUE as follows:
CREATE TEMP TABLE TABLE1 AS
(SELECT NAME,MAX(Value) value FROM `table` GROUP BY Name having count(*) >1
AND MAX(Value) != MIN(Value)
);
Use this temporary table to do your update as follows:
UPDATE
Table_A
SET
Table_A.value = Table_B.value
FROM
`table` AS Table_A
INNER JOIN TABLE1 AS Table_B
ON Table_A.NAME = Table_B.NAME
Also this code is somewhat of an approximation as i am not familiar with mysql but i am familiar with sql.
Let me know if this doesn't help.
Simple left join would do the trick.
Try this out and let me know in case of any queries.
select a.id,a.name,b.value
from
table a
left join
(select name,max(value) as value from table group by name) b
on a.name=b.name;
You may use this query. The table is joined with a subquery (table t2) that contains the results you want to update your table with:
UPDATE `table` t1,
(SELECT Name, MAX(Value) maxv, MIN(Value) minv
FROM `table`
GROUP BY Name
HAVING COUNT(*)>1 AND maxv != minv) t2
SET t1.Value = t2.maxv
WHERE t1.Name = t2.Name;
If you want to know how will the values be updated, you can first run an equivalent SELECT query:
SELECT t1.*, t2.maxv
FROM `table` t1,
(SELECT Name, MAX(Value) maxv, MIN(Value) minv
FROM `table`
GROUP BY Name
HAVING COUNT(*)>1 AND maxv != minv) t2
WHERE t1.Name = t2.Name;
This query will display all the fields of table, followed by the new value maxv. You can check the current value and the new value, and if it looks fine, you may run the UPDATE query.
I have a table like the following:
| ID | Short Name | Long Name |
|----|------------|-----------|
| 1 | s1 | l2 |
| 2 | s1 | l2 |
| 3 | s1 | l2 |
| 4 | s5 | l6 |
| .. | ... | |
I want to get all records that share the same Short Name and Long Name. I need their shared short name, long name, and 3 duplicates' IDs. For this particular example, I want {s1, l2, 1,2,3}
This is a fairly simple problem to solve. Basically what you want to do is write a subquery that counts the number of rows that match on your specified field for each row in your query. I have included a few examples below.
Find all rows that are duplicates and match on both name fields
SELECT * FROM TableName WHERE (SELECT COUNT(*) FROM TableName AS T2 WHERE T2.ShortName = TableName.ShortName AND T2.LongName = TableName.LongName) > 1;
Find all rows that are duplicates and match on the short name
SELECT * FROM TableName WHERE (SELECT COUNT(*) FROM TableName AS T2 WHERE T2.ShortName = TableName.ShortName) > 1;
Find all rows that are duplicates and match on the long name
SELECT * FROM TableName WHERE (SELECT COUNT(*) FROM TableName AS T2 WHERE T2.LongName = TableName.LongName) > 1;
Simply use a a self join of your table and select those rows where the two names are equal and the ids differ:
SELECT *
FROM <table> t1, <table> t2
WHERE t1.id <> t2.id
AND t1.short_name = t2.short_name
AND t1.long_name = t2.long_name;
You can use exits to see if there are any other data exists with the same condition where ID is not same.
select t1.* from table_name t1
where exists (
select 1 from table_name t2
where
t1.ID <> t2.ID
and t1.`Short Name` = t2.`Short Name`
and t1.`Long Name` = t2.`Long Name`
);
Is it possible to select the next lower number from a table without using limit.
Eg: If my table had 10, 3, 2 , 1 I'm trying to select * from table where col > 10.
The result I'm expecting is 3. I know I can use limit 1, but can it be done without that?
Try
SELECT MAX(no) no
FROM table1
WHERE no < 10
Output:
| NO |
------
| 3 |
SQLFiddle
Try this query
SELECT
*
FROM
(SELECT
#rid:=#rid+1 as rId,
a.*
FROM
tbl a
JOIN
(SELECT #rid:=0) b
ORDER BY
id DESC)tmp
WHERE rId=2;
SQL FIDDLE:
| RID | ID | TYPE | DETAILS |
------------------------------------
| 2 | 28 | Twitter | #sqlfiddle5 |
Another approach
select a.* from supportContacts a inner join
(select max(id) as id
from supportContacts
where
id in (select id from supportContacts where id not in
(select max(id) from supportContacts)))b
on a.id=b.id
SQL FIDDLE:
| ID | TYPE | DETAILS |
------------------------------
| 28 | Twitter | #sqlfiddle5 |
Alternatively, this query will always get the second highest number based on the inner where clause.
SELECT *
FROM
(
SELECT t.col,
(
SELECT COUNT(distinct t2.col)
FROM tableName t2
WHERE t2.col >= t.col
) as rank
FROM tablename t
WHERE col <= 10
) xx
WHERE rank = 2 -- <<== means second highest
SQLFiddle Demo
SQLFiddle Demo (supports duplicate values)
If you want to get next lower number from table
you can get it with this query:
SELECT distinct col FROM table1 a
WHERE 2 = (SELECT count(DISTINCT(b.col)) FROM table1 b WHERE a.col >= b.col);
later again if you want to get third lower number you can just pass 3 in place of 2 in where clause
again if you want to get second higher number, just change the condition of where clause in inner query with
a.col <= b.col
I have the next table:
+---------+------------+
| firm_id | service_id |
+---------+------------+
| 6 | 2 |
| 6 | 4 |
| 23 | 7 |
| 23 | 6 |
I want to get ONLY companies who do not have service_id=4 in their service list.
A query of the above table should return only the company with firm_id=23 because firm_id=6 has one record with service_id=4.
I want to make it with one query. Is this possible (without joins)?
Thanks.
P.S. Thanks everyone. User "derobert" suggested very interesting way, what i was looking for.
You can do it several ways. Here is one, with a correlated subquery:
SELECT DISTINCT firm_id FROM table t1
WHERE NOT EXISTS ( SELECT 1 FROM table t2 WHERE t1.firm_id = t2.firm_id AND t2.service_id = 4)
In MySQL-land it is often better to rewrite as a self-join:
SELECT DISTINCT firm_id
FROM table t1 LEFT JOIN table t2 ON (t1.firm_id = t2.firm_id AND t2.service_id = 4)
WHERE t2.firm_id IS NULL
Finally, here is one way to do it that doesn't involve subqueries or joins (but I expect performs worse than either of the above)
SELECT firm_id, CONCAT(',', GROUP_CONCAT(service_id SEPARATOR ','), ',') AS service_ids
FROM table t1
GROUP BY firm_id
HAVING service_ids NOT LIKE '%,4,%'
I confess I haven't actually run these; please forgive typos.
SELECT DISTINCT
firm_id
FROM
TableX AS t
WHERE
NOT EXISTS
( SELECT
*
FROM
TableX AS s
WHERE
s.firm_id = t.firm_id
AND
s.service_id = 4
)
or:
SELECT
firm_id
FROM
TableX
GROUP BY
firm_id
HAVING
COUNT(service_id = 4) = 0
You could try
SELECT * FROM your_table
WHERE firm_id NOT IN
(SELECT DISTINCT firm_id FROM your_table
WHERE service_id = 4) a
As suggested by ypercube (thanks!) you can also try
SELECT DISTINCT firm_id, service_id FROM your_table
WHERE firm_id NOT IN
(SELECT firm_id FROM your_table
WHERE service_id = 4) a