Getting a row based on a certain condition in sql self-join - mysql

For the following table, is it possible to get the result using a self-join?
Table:
id pId type
-------------
1 1000 1
2 1001 1
3 1002 1
4 1000 3
Expected result:
id pId type
-------------
2 1001 1
3 1002 1
In other words, I want all the rows which has type 1, but does not have type 3.
Thank you in advance.
UPDATE
this is a question in the context of a performance testing.
in other words, there are many rows like 1000 and 1001, 1002.
i'm trying to improve the performance using the current table structure.
but i understand that probably the table is not well-designed as well.

You don't need any joins - just a subselect - something like this:
select * from mytable t1
where not exists (select id from mytable t2 where t1.pid=t2.pid and type=3)

If you want to use a self join, you could use this query:
SELECT t1.id, t1.pId, t1.type
FROM
tablename t1 LEFT JOIN tablename t2
ON t1.pid = t2.pid AND t2.type=3
WHERE
t1.type=1 AND
t2.type IS NULL
Please see fiddle here.

Related

how to remove duplicate entries from many to many relation using sql query

My tables look like this. my op and country is having many to many relationships with each other.
OP
id, name,.....
op_country
id, op_id, country_id
country
id, name, ...
my op_country filled like below
id op_id country_id
1 1 1
2 1 2
3 2 2
4 2 3
5 3 3
6 3 3
7 1 1
I want to remove my duplicate entries from op_country. Here I want to remove rows 6 and 7 since we already have rows with such values.
How can I do that.
DELETE t1
FROM op_country t1
JOIN op_country t2 USING (op_id, country_id)
WHERE t1.id > t2.id
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=247ebc5870a6ab10b64076ffb375797f
You want to delete entries for which exists a sibling with a lower ID:
delete from op_country
where exists
(
select null
from (select * from op_country) op2
where op2.op_id = op_country.op_id
and op2.country_id = op_country.country_id
and op2.id < op_country.id
);
The from (select * from op_country) is necessary instead of a mere from op_country due to some weird restriction in MySQL updates.

Seperate comma and get value from another table and concatenate result value

Suppose firstly my table1 is:
id name
----------
1 abc
2 bcd
3 cde
In table2 i store
id table1_id
------------
1 1,2
2 1,3
3 1,2,3
I want output like this
id table1_value
----------------
1 abc,bcd
2 abc,cde
3 abc,bcd,cde
Please help me in with mysql query..
Below is a query which should meet your requirements. As #GurV commented above, you should avoid storing CSV data in your table, which is not normalized, and which thwarts much of the power which MySQL has as a relational database.
SELECT t2.id,
GROUP_CONCAT(t1.name ORDER BY t1.name) AS table1_value
FROM table2 t2
INNER JOIN table1 t1
ON FIND_IN_SET(t1.id, t2.table1_id) > 0
GROUP BY t2.id
Output:
Demo here:
Rextester

Removing duplicates by max date

I have a table in my MySQL database that I need to remove the duplicates from.
My table looks something like this:
unique_id value frequency value_type publication_date
1 6.5 1 2 2014-12-31
2 7.5 3 5 2014-06-04
3 6.5 1 2 2015-07-13
4 8.0 4 3 2010-12-31
Rows 1 and 3 are duplicates except for the publication_date. I need to remove these duplicates but keep the row with the max publication date so for this example I would want to remove row 1 and keep row 3.
So far I've tried this but it's giving me too many results on my test table:
SELECT t.* FROM
(SELECT MAX(publication_date) AS most_recent_date
FROM table_1
GROUP BY `value`,frequency,value_type
) t1
JOIN table_1 t
ON t.publication_date = t1.most_recent_date;
Any help would be appreciated.
Thanks.
You can use JOIN to remove the duplicates as
delete t1 from table_1 t1
join table_1 t2 on t1.value = t2.value
and t1.frequency= t2.frequency
and t1.value_type = t2.value_type
and t1.unique_id <> t2.unique_id
and t1.publication_date < t2.publication_date ;

selecting one column from 3 different tables

I have 3 tables:
Table 1: columns are:
+------+-------+----------+----------+
| date | time | user_id | channel |
+------+-------+----------+----------+
Table 2:
+---------+------------+
| user_id | id _number |
+---------+------------+
Table 3:
+---------+-------+
| channel | sort |
+---------+-------+
In table 1 the columns are sorted as following :
2011-07-29, 12:35:15.650, 22, DeluxeMusic
In table 2 :
130.83.10.c42ce82365b9f6d , 22 (same as user_id in table 1)
In table 3:
DeluxeMusic (same as in table 1), entertainment.
The columns user_id in table 2 : 130.83.10.c42ce82365b9f6d means a user_id of some user. From this user ID I need to get all entries with the value of 130 in the begining. For all entries with same value 130.
Then I need to seek for this value of 130 in the table 3 the sort of channel they are watching, and to count by that all users watching a channel typ.
Channel typs are also : sport, shopping, entertainment and so on.
you could try this too:
select count(*) from t1 join t2 on t1.id = t2.id and t2.userid like '130%' join
t3 on t1.channel = t3.channel group by t1.channel
sql fiddle here
Edit:
another version:
select count(t1.id) , t1.*, t2.*, t3.*
from t1 join t2 on t1.id = t2.id join
t3 on t1.channel = t3.channel and t2.userid
like '130%' group by t3.channel, t1.id
fiddle
Not sure if I get your question completely. But from what I understand you would be needing something like below:
SELECT COUNT (*) FROM TABLE1 T1,TABLE2 T2,TABLE3 T3
WHERE T1.USER_ID = T2.USER_ID
AND T1.USER_ID LIKE '130%'
AND T1.CHANNEL = T3.CHANNEL
The above sql would be the used to fetch the count of the channels that the users with their use ids beginning with '130' would be watching.
Hopefully this should help you in someway.

SQL count each distinct value in column and add name from another table where the ID matches

My SQL Skills are next to none. After looking around for the past 2 hours trying to figure this out I need some help please.
I have 2 tables as below
Table1 Table2
ID | Name Status_id
----------- ----------
1 | Open 1
2 | Closed 2
3 | On-Hold 1
What I would like to do is count the status_id in table 2 and group by the status_id. Then add the Name where the ID matches in the first column.
What I have at the moment is
SELECT status_id, COUNT(*) AS 'num' FROM table2 GROUP BY status_id
This is great so far and returns
1 | 2
2 | 1
What I need to return is
Open | 2
Closed | 1
I hope that is clear. Can anyone help?
Many thanks!
SELECT a.name, COUNT(*) AS num FROM table2 b
INNER JOIN table1 a
ON b.status_id=a.id
GROUP BY status_id
In the case that you want to also have Zero for On-Hold you'd need to do a LEFT join and count the a column from table2 instead of *
SELECT t1.name,
Count(t2.Status_id) AS num
FROM table1 t1
LEFT JOIN table2 t2
ON t1.id = t2.Status_id
GROUP BY t1.name;
DEMO