mySQL SELECT based on its result - mysql

I have a table like this:
| id | parentID | columnName |
|----|----------|-------------------|
| 1 | 2 | John |
| 2 | 0 | Task name |
| 3 | 4 | John |
| 4 | 0 | Task another name |
I want to get John task, but also with its name so I'm wondering if it is any way to do it in single MySQL query?
SELECT id, parentID, person FROM table WHERE columnName = "John"
will result in user task, but I want to know how this task is named.

You seem to be looking for a self-join:
select
t.id,
t.parentid,
t.columnname person,
t1.columnname task
from mytable t
left join mytable t1 on t1.id = t.parentid
where t.person = 'John'

Related

Fetching a distinct column only if duplicates columns have the same data

I have this type of table:
+-----TABLE1----+
| Name, Boolean |
| A , 0 |
| B , 0 |
| B , 0 |
| A , 1 |
| C , 1 |
| D , 0 |
| C , 0 |
| A , 0 |
| A , 1 |
| B , 0 |
| D , 0 |
+--------------+
I want to select distinct all names that their duplicates booleans are 0 aswell.
So the result will be:
+---------------+
| RESULT: |
| Name |
| B |
| D |
+---------------+
Because A and C contains boolean also of "1" so they wont be fetched
I can do:
SELECT DISTINCT name, MAX(boolean) as boolean FROM table1 GROUP BY name;
But what condition I need to use if I want to fetch only the results that their max(boolean) are 0?
I can't use two select statements inside one query because we are talking about big data database..
so this solution is not an option in my case:
SELECT DISTINCT t1.name FROM table1 t WHERE t1.name NOT IN (SELECT DISTINCT t2.name FROM table1 t2 WHERE t2.boolean = 1);
Couldn't think of an option when using "JOIN" aswell.
Any solutions?
Thanks in advance! :)
You can use aggregation:
select name
from table1 t
group by name
having min(boolean) = max(boolean);

MySQL NOT IN Select

I have a following table in my project
+----+--------+-----------+-----------+
| id | old_id | op_status | tr_status |
+----+--------+-----------+-----------+
| 1 | | issue | Approved |
| 2 | | issue | Approved |
| 3 | | issue | Approved |
| 4 | 1 | issue | Issued |
| 5 | 3 | issue | Issued |
+----+--------+-----------+-----------+
I want to select records WHERE tr_status='Approved' and NOT IN id in the old_row_id. In this example no need to select id(s) 1 and 3 that are in old_row_id as the following result.
+----+--------+-----------+-----------+
| id | old_id | op_status | tr_status |
+----+--------+-----------+-----------+
| 2 | | issue | Approved |
+----+--------+-----------+-----------+
I used the following query.
SELECT id, old_row_id, op_status, tr_status FROM table WHERE id NOT IN (old_row_id).
But outs the following result.
+----+--------+-----------+-----------+
| id | old_id | op_status | tr_status |
+----+--------+-----------+-----------+
| 1 | | issue | Approved |
| 2 | | issue | Approved |
| 3 | | issue | Approved |
+----+--------+-----------+-----------+
What may be wrong with me ? can anyone help me ?
I would phrase your query using exists logic:
SELECT t1.id, t1.old_id, t1.op_status, t1.tr_status
FROM yourTable t1
WHERE
t1.tr_status = 'Approved' AND
NOT EXISTS (SELECT 1 FROM yourTable t2 WHERE t2.old_id = t1.id);
Demo
Try doing something like this:
SELECT id, old_id, op_status, tr_status
FROM table
WHERE id NOT IN (SELECT DISTINCT old_id FROM table)
AND tr_status = 'Approved'
You will want to left join the table to itself on the old ID, then eliminate the records where there is a match.
For example:
SELECT A.id, A.old_row_id, A.op_status, A.tr_status
FROM table A
LEFT JOIN table B ON A.id = B.old_row_id
WHERE B.id IS NULL
AND A.tr_status = 'Approved';
In they way you've tried to solve it, you're matching the old_id with the value of the row itself. You must derivate the table to create a cartesian product:
SELECT id, old_id, op_status, tr_status
FROM table
WHERE id NOT IN (SELECT IFNULL(old_id, 0) FROM table)
AND tr_status = 'Approved'
Also IFNULL to also include those record in the subquery, otherwise can't be compared with null

How can I select data from table1 with multiple attributes from table2 in mysql?

I have two tables in mysql. The first one has user data for example, the second one has attributes data.
I want to select each user from table one and get all attributes for him from table two.
e.g.
table 1:
| userid | name |
| 1 | John |
| 2 | Billie |
table 2:
| userid | attribute |
| 1 | male |
| 1 | taxi driver |
| 1 | 45 years |
| 2 | female |
| 2 | clerk |
So I want to get my mysql results like this:
| userid | name | attributes |
| 1 | John | male, taxi driver, 45 years |
| 2 | Billie | female, clerk |
I absolutely have noch idea, how to get these attributes consolidated (maybe even comma seperated). I also searched here, but found nothing similar.
Can you help please? Thanks
I think you can user GROUP_CONCAT for that perhaps.
SELECT userid, name, GROUP_CONCAT(attribute) as attributes
FROM table1
INNER JOIN table2 ON table1.userid = table2.userid
GROUP BY table2.userid
See this SQLFiddle example: http://sqlfiddle.com/#!9/fd365d4/6/0
;with SampleDataR as
(
select *, ROW_NUMBER() over (partition by title, subtitle order by value) rownum
from test12
)
select distinct title, subtitle,(
select value
+ case when s1.rownum = (select MAX(rownum) from SampleDataR where title = s1.title and subtitle = s1.subtitle)
then '' else ',' end from SampleDataR s1
where s1.title = s2.title and s1.subtitle = s2.subtitle
for xml path(''),type).value('(.)[1]','varchar(max)') csvList
from SampleDataR s2

Mysql delete duplicate record but keep the row which contain most value

if I have following table :
+------+--------+---------+-------+-------+
| id | name | Surnmae | email |address|
+------+--------+---------+-------+-------+
| 1 | | Lee | aaa |23 a st|
| 2 | a | | aaa | |
| 3 | c | | ccc | |
+------+--------+---------+-------+-------+
How can I delete duplicate record base on email but keep the record which contains most value and give the following result?
+------+--------+---------+-------+-------+
| id | name | Surnmae | email |address|
+------+--------+---------+-------+-------+
| 1 | | Lee | aaa |23 a st|
| 3 | c | | ccc | |
+------+--------+---------+-------+-------+
I got a way, but it is kind ok stupid, it works for small table just like the one I provided above:
DELETE FROM table1
WHERE firstname NOT IN (SELECT *
FROM (SELECT MAX(n.firstname)
FROM table1 n
GROUP BY n.email) x)
OR lastname NOT IN (SELECT *
FROM (SELECT MAX(n.lastname)
FROM table1 n
GROUP BY n.email) x)
OR address NOT IN (SELECT *
FROM (SELECT MAX(n.address)
FROM table1 n
GROUP BY n.email) x)
but does anyone has an idea which can simplif my query?? like one line query?
Please try this i assume ur table name is members
delete t1 from members LEFT JOIN members t1 ON members.email = t1.email AND members.id != t1.id AND IFNULL(CHAR_LENGTH(members.Surnmae ),0) > IFNULL(CHAR_LENGTH(t1.Surnmae ),0) WHERE t1.id > 0;

Exctract specific data with self-check

I have this kind of table with data:
+-------------+------------+------------+
| Name | Test1 | Test2 |
+-------------+------------+------------+
| A | 1 | 1 |
+-------------+------------+------------+
| A | 1 | 1 |
+-------------+------------+------------+
| A | 0 | 2 |
+-------------+------------+------------+
| B | 1 | 1 |
+-------------+------------+------------+
| B | 2 | 1 |
+-------------+------------+------------+
| C | 1 | 1 |
+-------------+------------+------------+
| C | 1 | 1 |
+-------------+------------+------------+
I need to get all names that have all in field test1 and test2 values 1.
In this case output should be like:
+-------------+------------+
| C | PASS |
+-------------+------------+
Because all records whose name is C and have Test1=1 and Test2=1 are passed,
For example record A cannot pass because one of row have Test1=0 and Test=2.
Same is for B. B have only one record with Test1=1 and Test2=1 but the next record for B have Test1=2 and Test2=1.
How to make query that can extract those data? Or this is better to solve through code?
Combine both Test1 and Test2 columns with UNION.
Then select the name which having both minimum and maximum test value as 1.
Query
select name,'PASS' as `status`
from
(
select name,test1 as test
from tests
union all
select name,test2 as test
from tests
)t
group by name
having max(t.test) = 1
and min(t.test) = 1;
SQL Fiddle
My idea is to first choose names that do not fill your rule and then select all remaining ones. Is this your logic?
select distinct name, 'PASS' from table
where name not in
(select name from table where test1 <> 1 or test2 <> 1);
SELECT DISTINCT name, "PASS" FROM yourtable WHERE test1 = 1 AND test2=1