SQL Query to fetch results from a table - mysql

Many thanks for any help.
I have a following table consisting of 2 columns service_id and artist_id. Primary Key is (service_id, artist_id). I want to retrieve all the artists for a set of service ids.
Sample Table :
service_id artists_id
5 9
6 9
5 10
1 9
5 1
6 1
6 7
1 10
I tried this and it is not working as it gives all the artists who give either service id 5 or service id 6 or service id 1.
SELECT artists_id FROM `service_schedule` WHERE service_id IN (5, 6, 1)
I want artists who give service id 5 And Service Id 6 And Service Id 1. For the above sample table only artist 9 gives all the 3 services in the set (5,6,1).
So if i want to retrieve all artists who can give services with id 5 and 6 and 1. How do i write a SQL query?

Once try this,
select artist_id from table where service_id IN (5, 6) AND
artist_id IN (select artist_id from table group by artist_id having count(*) > 1);
I am fetching all artist_id which has count greater than 1 and must be service_id with 5 and 6.
I hope this will help.
EDIT
select artists_id from Sample where service_id IN (5, 6, 1)
AND
artists_id IN (select artists_id from Sample group by artists_id
having count(*) > 2) group by artists_id;
You can get, service_ids like, 5,6 or 5,6,1, you just need to take count of service ids and then keep that value - 1 in place of 2
EDIT
select * from Sample where service_id IN (5, 6, 1, 8) and is_available = 1
AND
artists_id IN (select artists_id from Sample where is_available = 1 group by artists_id
having count(*) > 3) group by artists_id;

You have to use a group by query:
select
artist_id
from
service_schedule
group by
artist_id
having
sum(service_id in (5,6,1))=3
service_id in (5,6,1) will be evaluated as 1 when the condition is true, and you want to check if for every artist_id the sum is 3 (all three services are given - arist_id and service_id is unique so no need to check about duplicated rows here)

The question is not much clear to me but is following solution works for you if I understood it clearly.
select s1.service_id, s1. artists_id
from Sample s1 inner join Sample s2
on s1.artists_id = s2.artists_id
where s2.service_id = 5 and s1.service_id = 6
union
select s1.service_id, s1. artists_id
from Sample s1 inner join Sample s2
on s1.artists_id = s2.artists_id
where s2.service_id = 6 and s1.service_id = 5
Sample Output - http://sqlfiddle.com/#!9/7b3a5/16

Try this:
SELECT DISTINCT(s1.artists_id) FROM service_schedule s1
JOIN service_schedule s2 ON s2.service_id = s1.service_id AND s2.artists_id <> s1.artists_id
WHERE s1.service_id IN (5, 6, 1)

Related

MySQL Putting in duplicate id's

I'm trying to run an UPDATE query that uses the same table and I'm getting an error saying "1093 - Table 'queues_monitor_times' is specified twice, both as a target for 'UPDATE' and as a separate source for data".
UPDATE queues_monitor_times
SET queue_id = IF((
SELECT id
FROM queues_monitor_times
INNER JOIN(
SELECT pcc_group, pcc, gds, queue, category, `name`
FROM queues_monitor_times
GROUP BY pcc_group, pcc, gds, queue, category, `name`
HAVING COUNT(id) > 1
)temp ON queues_monitor_times.pcc_group = temp.pcc_group AND
queues_monitor_times.pcc = temp.pcc AND
queues_monitor_times.gds = temp.gds AND
queues_monitor_times.queue = temp.queue AND
queues_monitor_times.category = temp.category AND
queues_monitor_times.`name` = temp.`name`), 1, id)
WHERE
id NOT IN (SELECT MIN(id) FROM queues_old GROUP BY pcc_group, pcc, gds, queue, category, `name`);
I ran the select query by itself and it showed all the rows that were duplicates, which is what I wanted. I want queue_id to be set with the lowest duplicate row's id if the row is a duplicate or the row id if it is not.
Example of what the query should do:
id dup_id name value
1 1 John 13
2 2 John 13
3 3 Sally 6
4 4 Frank 4
5 5 Sally 6
And after running the query it will turn into
id dup_id name value
1 1 John 13
2 1 John 13
3 3 Sally 6
4 4 Frank 4
5 3 Sally 6
Please advise and thank you for your help.
I was able to solve my problem. Thanks for all your help!
UPDATE queues_monitor_times
SET queue_id = (
SELECT
id
FROM
queues_old
WHERE
queues_old.pcc_group = queues_monitor_times.pcc_group
AND queues_old.pcc = queues_monitor_times.pcc
AND queues_old.gds = queues_monitor_times.gds
AND queues_old.queue = queues_monitor_times.queue
AND queues_old.category = queues_monitor_times.category
AND queues_old.`name` = queues_monitor_times.`name`
GROUP BY pcc_group, pcc, gds, queue, category, `name`
HAVING COUNT(id) > 1)
WHERE
id NOT IN (SELECT MIN(id) FROM queues_old GROUP BY pcc_group, pcc, gds, queue, category, `name`);
For those that will want to use this in the future, queues_monitor_times table and queues_old table have the exact same data.

MySQL query to find ids that do not exist in table

I have a list of ids pre-generated that I need to check if exist in a table. My table has two columns, id, name, where id is an auto increment integer and name is a varchar(255).
I basically want to get a count of how many ids do not exist in table foo from my pre-generated list. So say my list has the numbers 5 and 10 in it, what's the best way to write something to the extent of:
select count(*) from foo where id does not exist in ( 5, 10 )
The idea here is that if 5 and 10 do not exist, I need the response 2, and not the number of rows in foo that do not have the id 5 or 10.
TL; DR sample data and queries at rextester
The idea here is that if 5 and 10 do not exist, I need the response 2, and not the number of rows in foo that do not have the id 5 or 10.
You should have provided a little more information to avoid confusion.
Example
id | name
1 | tom
2 | joe
3 | mae
4 | goku
5 | vegeta
If your list contains (1, 2, 3) then your answer should be 0 (since all three are in the table )
If your list contains (1, 2, 6) then your answer should be 1. ( since 1 and 2 are in the table but 6 is in't )
If your list contains (1, 6, 7) then your answer should be 2.
If your list contains (6, 7, 8) then your answer should be 3.
assuming this was your question
If you know the length of your list
select 2 - count(*) as my_count from foo where id in (5, 10)
The following query tells you how many are present in foo.
select count(*) from foo where id in (5,10)
So if you want to find those that do not exist, subtract this result from the length of your list.
select n - count(*) as my_count from foo where id in (5, 10,....)
You could use on fly table using union and the a left join
select count(*)
from my_table as m
left join (
select 5 as id from dual
union
select 10 from dual ) t on t.id = m.id
where t.id is null
otherwise you can populate a tempo table with the value you need and use left join
where the value is null

Count first occurence with column value ordered by another column

I have an assigns table with the following columns:
id - int
id_lead - int
id_source - int
date_assigned - int (this represents a unix timestamp)
Now, lets say I have the following data in this table:
id id_lead id_source date_assigned
1 20 5 1462544612
2 20 6 1462544624
3 22 6 1462544615
4 22 5 1462544626
5 22 7 1462544632
6 25 6 1462544614
7 25 8 1462544621
Now, lets say I want to get a count of the rows whose id_source is 6, and is the first entry for each lead (sorted by date_assigned asc).
So in this case, the count would = 2, because there are 2 leads (id_lead 22 and 25) whose first id_source is 6.
How would I write this query so that it is fast and would work fine as a subquery select? I was thinking something like this which doesn't work:
select count(*) from `assigns` where `id_source`=6 order by `date_assigned` asc limit 1
I have no idea how to write this query in an optimal way. Any help would be appreciated.
Pseudocode:
select rows
with a.id_source = 6
but only if
there do not exist any row
with same id_lead
and smaller date_assigned
Translate it to SQL
select * -- select rows
from assigns a
where a.id_source = 6 -- with a.id_source = 6
and not exists ( -- but only if there do not exist any row
select 1
from assigns a1
where a1.id_lead = a.id_lead -- with same id_lead
and a1.date_assigned < a.date_assigned -- and smaller date_assigned
)
Now replace select * with select count(*) and you'll get your result.
http://sqlfiddle.com/#!9/3dc0f5/7
Update:
The NOT-EXIST query can be rewritten to an excluding LEFT JOIN query:
select count(*)
from assigns a
left join assigns a1
on a1.id_lead = a.id_lead
and a1.date_assigned < a.date_assigned
where a.id_source = 6
and a1.id_lead is null
If you want to get the count for all values of id_source, the folowing query might be the fastest:
select a.id_source, count(1)
from (
select a1.id_lead, min(a1.date_assigned) date_assigned
from assigns a1
group by a1.id_lead
) a1
join assigns a
on a.id_lead = a1.id_lead
and a.date_assigned = a1.date_assigned
group by a.id_source
You still can replace group by a.id_source with where a.id_source = 6.
The queries need indexes on assigns(id_source) and assigns(id_lead, date_assigned).
Simple query for that would be
check here http://sqlfiddle.com/#!9/8666e0/7
select count(*) from
(select * from assigns group by id_lead )t
where t.id_source=6

Fetching data from mapping table

I have a table structure like this:
bundle_id|service_id
8|1
8|2
8|3
9|1
9|4
10|1
10|2
10|3
10|4
10|5
Now, I want to query the table to fetch the optimal bundle which has particular set of services.
E.g. If I want to fetch the bundle having services 1,2 and 3 then it should return 8 (and not 10).
Can anyone please help me with the query?
Try this:
SELECT bundle_id
FROM mappings
WHERE service_id IN (1, 2, 3)
GROUP BY bundle_id HAVING COUNT(DISTINCT service_id) = 3
ORDER BY bundle_id LIMIT 1;
EDIT
SELECT m.bundle_id
FROM mappings m
INNER JOIN (SELECT bundle_id, COUNT(DISTINCT service_id) serviceIdCnt
FROM mappings GROUP BY bundle_id
) A ON m.bundle_id = A.bundle_id
WHERE m.service_id IN (1, 2, 3)
GROUP BY m.bundle_id HAVING COUNT(DISTINCT m.service_id) = 3
ORDER BY A.serviceIdCnt LIMIT 1;
Check the SQL FIDDLE DEMO
OUTPUT
| BUNDLE_ID |
|-----------|
| 8 |

How can I update this SQL query to give the result I want?

I have two tables as follow:
listings Table
listing_id
----------
111111
111113
listings_features_table
id listing_id feature_id
------------------------------
1 111111 4
2 111111 1
5 111113 9
6 111113 1
7 111113 4
I am trying to get only results that have all feature_id I specify. So in my case, if I specify (1, 4, 9), only listing_id 111113 has these in the feature_id column and that's what I want returned.
I've tried using IN in my query, but it's equivalent to OR, and that's why am getting a wrong result.
Following is the query am using:
SELECT * FROM listings_features
JOIN listings ON listings.listing_id=listings_features.listing_id
WHERE listings_features.feature_id IN (1,4,9) GROUP BY listings.listing_id
which gives this result:
id listing_id feature_id listing_id
----------------------------------------------
1 111111 4 111111
5 111113 9 111113
is there any way I can use to get the following result instead:
id listing_id feature_id listing_id
----------------------------------------------
5 111113 1, 4, 9 111113
Or shall I do that on the php level?
Here is a trick using group_concat() for the comparison:
SELECT *
FROM listings_features lf JOIN
listings l
ON l.listing_id = lf.listing_id
WHERE lf.feature_id in (1,4,9)
GROUP BY l.listing_id
HAVING group_concat(distinct lf.feature_id order by lf.feature_id) = '1,4,9';
If you want those features but don't care about others, then remove the where clause.
NOTE: you have to know the number of features and adjust the 3 accordingly. but since you know you're looking for 1,4,9, you know you have 3 so passing in a variable for the count and populating it shouldn't be difficult.
SELECT ID, Listing_Features.Listing_Id, group_Concat(Feature_ID), Listings.Listing_Id
FROM listings_features
JOIN listings ON listings.listing_id=listings_features.listing_id
WHERE listings_features.feature_id IN (1,4,9) GROUP BY listings.listing_id
GROUP BY Listing_Features.ID, Listing_Features.Listing_Id, Listings.Listing_Id FROM listings_features
HAVING count(*) = 3
SELECT ID, MAX(Listings_features.Listing_ID), group_concat(Feature_ID), MAX(Listings.Listing_ID) from Listings_Features
inner join Listings USING (listing_id)
WHERE Listings_Features.feature_id IN(1,4,9)
GROUP BY ID;
Probably messed up on the table names. I listings and listing all look the same...but generally...