Group or eliminate duplicates fields in columns - mysql

I want to group the data of the field 1 that has more data in the field 2
+-----+----------+---------------+
| id | field1 | field2 |
+-----+----------+---------------+
| 1 | ONE | Medicine |
| 2 | TWO | Food |
| 3 | TWO | Medicine |
+-----+----------+---------------+
I want something like this
+-----+----------+---------------+
| id | field1 | field2 |
+-----+----------+---------------+
| 1 | ONE | Medicine |
| 2 | TWO | Food |
| 3 | | Medicine |
+-----+----------+---------------+
I dont know if is possible im new in mysql
thanks for your time

You can use case when first record of group display the value, otherwise empty string:
SELECT ID,
CASE ROW_NUMBER() OVER (PARTITION BY field1) WHEN 1 THEN field1 ELSE "" END AS FIELD1,
field2
FROM table
;

This technique should work for any version
SELECT (
CASE WHEN (
SELECT count(b.f1)
FROM tbl b
WHERE b.f1 = a.f1 AND a.id > b.id) > 0
THEN '' ELSE a.f1 END) f1, a.f2
FROM tbl a
ORDER BY a.f1, a.id asc;

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 join only if a field has a particular value

I am trying to fetch a table on certain conditions with join. My table is:
tab_registrations
--------------------------------------------
reg_id |familyid| familyname | parent_id |
| | | |
-------|--------|-------------|-----------|
1 | 2 | null | null |
-------|--------|-------------|-----------|
2 | others | abc | 3 |
-------|--------|-------------|-----------|
3 | 3 | null | null |
-------|--------|-------------|-----------|
4 | others | def | 2 |
-------|--------|-------------|-----------|
tab_family
-------------------------------------
family_id | family_name | parent_id |
| | |
-------------------------------------
1 | tyu | 0 |
-------------------------------------
2 | xyz | 1 |
-------------------------------------
3 | mno | 2 |
-------------------------------------
I want to join these tables on:
if tab_registrations.family not equal to null, then select corresponding parent_id from tab_family
SELECT tab_registration.*,tab_family.family_id,tab_family.parent_id
FROM `tab_registration`
join tab_family on tab_registration.family_id = tab_family.family_id
WHERE reg_id = 1
if tab_registrations.family is equal to 'others', then select tab_registrations.familyname and tab_registrations.parent_id
When I try the above query if tab_registrations.family = 'others', no rows fetched
How can I achieve this? Can anyone help me?
Change to LEFT JOIN with the condition that tab_registration.familyid is not equal to others. Also, you can use conditional CASE..WHEN statements to get the familyname and parent_id values.
SELECT tr.*,
CASE WHEN tr.familyid = 'others' THEN tr.familyname
ELSE tf.family_name
END AS familyname,
CASE WHEN tr.familyid = 'others' THEN tr.parent_id
ELSE tf.parent_id
END AS parent_id
FROM tab_registration tr
LEFT JOIN tab_family tf
ON tr.family_id = tf.family_id AND
tr.familyid <> 'others'
WHERE tr.reg_id = 1
For multi-table queries, it if preferable to use Aliasing for code clarity and readability.
may be useful this query
SELECT tr.*,tf.family_id,tf.parent_id,
IF(tr.familyid='others',tr.familyname,tf.family_name) as fname
IF(tr.familyid='others',tr.parent_id,tf.parent_id) as parentId
FROM `tab_registration` tr
left join tab_family tf on tr.family_id = tf.family_id

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

SQL - Select same values in column then rename them

Is it possible in SQL to select values in a column then rename the duplicate ones? (assuming maximum of one possible duplicate only)
Let's say I have a table..
| id | name | 0or1_id |
| 0 | Eddy | 0 |
| 1 | Allan | 0 |
| 2 | Eddy | 1 |
| 3 | Allan | 1 |
What query can I do to make it like this?
| id | name | 0or1_id |
| 0 | Eddy | 0 |
| 1 | Allan | 0 |
| 2 | Eddy-copy | 1 |
| 3 | Allan-copy | 1 |
Assuming you want to actually change the data, use update:
update t join
(select name, count(*) as cnt, min(id) as minid
from t
group by name
having cnt > 1
) tt
on t.name = tt.name and t.id <> tt.minid
set name = concat(name, '-copy');
If you only want a select, then the logic is quite similar.
This will work in SQL Server..
select id , name ,0or1_id from (
select id , name ,0or1_id ,row_number() over (partition by name order by id ) as rnm
from table)z1
where rnm =1
union
select id , name || '- Copy' as new_name ,0or1_id from (
select id , name ,0or1_id ,row_number() over (partition by name order by id ) as rnm
from table)z2
where rnm > 2
http://sqlfiddle.com/#!9/3ebaf/1
UPDATE mytable t
INNER JOIN mytable t1
ON t.name = t1.name
AND t.id>t1.id
SET t.name = CONCAT(t.name,'-copy');

Need the last non-NULL row of a data set in mysql grouped by a 2nd field

I'm not too good at (my)SQL so here's a table and a question. I use the table to hold a history. I'd like to return the complete row that was most recent(*) and has a non-NULL value for field1. If there isn't such a row, I'd like to get any of the row where field1 was NULL.
*) Recent meaning, it has the highest id (the 'a'-'s below).
Table and example:
| id | field1 | field2 |
------------------------
| 1 | (null) | 34 | <--b
| 2 | 77 | 1234 |
| 3 | (null) | 1234 |
| 4 | (null) | 234 |
| 5 | (null) | 34 | <--b
| 6 | 99 | 1234 |
| 7 | 42 | 1234 | <--a
| 8 | 13 | 234 | <--a
| 9 | (null) | 234 |
I'd like to get three rows, as there are three distinct field2 values. I'd like the rows marked with an 'a' as they are most recent and have a non-NULL field1. And I'd like to have one of the two 'b'-'s (doesn't matter which one for me). Making three total.
I tried a statement like:
SELECT MAX(id), field1, field2
FROM table1
GROUP BY field2;
But that does not yield the desired result.
SELECT t.*
FROM
( SELECT DISTINCT field2
FROM table1
) AS dt
JOIN
table1 AS t
ON t.id = COALESCE(
( SELECT MAX(id) AS maxid
FROM table1
WHERE field2 = dt.field2
AND field1 IS NOT NULL
),
( SELECT MAX(id)
FROM table1
WHERE field2 = dt.field2
)
) ;
Another way:
SELECT t.*
FROM
( SELECT DISTINCT field2
FROM table1
) AS dt
JOIN
table1 AS t
ON t.id =
( SELECT id
FROM table1
WHERE field2 = dt.field2
ORDER BY (field1 IS NULL)
, id DESC
LIMIT 1
) ;
Tested in (your) SQL-Fiddle