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

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);

Related

How to filter rows with a column describing ranges in string in SQL

Assuming there are two tables follows:
table 1
| type | ranges |
| -------- | -------------- |
| type1 | 123,100-200|
| type2 | 250-500|
The ranges can be either continuous or discret values.
table 2
| id | value |
| -------- | -------------- |
| 1 | 260|
| 2 | 123|
How to write the select SQL to find type of each id belongs to?
select id,type
from table2
left join table1 on IS_VALUE_WITHIN_RANGE(table2.value,table1.ranges)
result:
| id | type|
| -------- | -------------- |
| 1 | type2|
| 2 | type1|
For example, id=1,value=260 is between 250-500 which should belong to type2, and value 123 matches type1.
Step1: Remove all ,
Step2: Split range by -, to get start and end range
Step3: Convert range to the integer type
step4: Perform the join with between to get the required output
with range_split as (
select
*,
REGEXP_SUBSTR(REPLACE(ranges,',',""),'\\d+') as range_start,
REGEXP_SUBSTR(REPLACE(ranges,',',""),'\\d+$') as range_end
from [table1]
),
to_integer_type as (
select
*,
cast(range_start as UNSIGNED) as range_start_int,
cast(range_end as UNSIGNED) as range_end_int
from range_split
)
select
table2.id,
to_integer_type.type
from table2
left join to_integer_type
on table2.value between to_integer_type.range_start_int and to_integer_type.range_end_int

mySQL SELECT based on its result

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'

Group or eliminate duplicates fields in columns

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;

How to calculate the number of the same values in a column in a complex query?

How to calculate the number of the same values in a column in a complex query?
I use this command:
SELECT
Table,id,first,second,third,code
FROM (
SELECT 't1' AS 'Table',id, first, second, third, code FROM x_table1
UNION ALL
SELECT 't2' AS 'Table',id,first,second,third,code FROM x_table2
) tbl
GROUP BY id, first, second, third, code
HAVING count(*) = 1
ORDER BY id
The result of the query:
id
t1 | 10 | something1 | something | something1 | something
t2 | 10 | something1 | something | something2 | something
t1 | 33 | something3 | something | something | something
As a result, I get the number of the records in the column. Now I would need to add a column where I would have the same IDs.
Example, I want first column:
count id
2 | t1 | 10 | something1 | something | something1 | something
2 | t2 | 10 | something1 | something | something2 | something
1 | t1 | 33 | something3 | something | something | something
Could you give me an advice please? Thank you very much.
Right solution:
SELECT
(
SELECT COUNT(id_zaznam) FROM
(
SELECT * FROM x_table1
UNION ALL
SELECT * FROM x_table2
) temp WHERE temp.id_zaznam = tbl.id_zaznam
) AS 'pocet',
Tabulka,id_zaznam,prvni,druhy,treti,kod
FROM (
SELECT 't1' AS 'Tabulka',id_zaznam, prvni, druhy, treti, kod FROM x_table1
UNION ALL
SELECT 't2' AS 'Tabulka',id_zaznam,prvni,druhy,treti,kod FROM x_table2
) tbl
GROUP BY id_zaznam, prvni, druhy, treti, kod
HAVING count(*) = 1
ORDER BY id_zaznam

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');