select when record change value - mysql

I'm trying to select just records which changed values compared to previous record,
my table is looking like this
Id(int) | value(boolean) |
-------------------------
1 | 0 |
-------------------------
2 | 1 |
-------------------------
3 | 1 |
-------------------------
4 | 1 |
-------------------------
5 | 0 |
-------------------------
6 | 0 |
-------------------------
I must get id:2,5
thanks for your help

I did a self-join, but instead of joining identical ids, I join t1.id = t2.id-1 and then compare the values:
select t2.id
from thetable t1
inner join thetable t2 on t1.id = t2.id-1
where t1.value != t2.value
sqlfiddle: http://sqlfiddle.com/#!2/6d626/4
Edit to add:
Thanks to #Ravinder, I figured out a way to do this even if the ids aren't sequential.
I used this related question.
SET #a :=0;
SET #b :=1;
SELECT t1.id, t1.rownum
FROM
(SELECT if(#a, #a:=#a+1, #a:=1) as rownum, id, value FROM thetable) AS t1
LEFT JOIN
(SELECT if(#b, #b:=#b+1, #b:=1) as rownum, id, value FROM thetable) AS t2
ON t1.rownum = t2.rownum
where t2.value != t1.value
SQLFiddle with non-sequential ids
Basically if you don't have sequential ids you create your own. I called them rownum.

You can use mysql variable in query to check if its new or unchanged
SELECT
`Id`,
`value`,
(CASE when #test=value then 'unchanged'
else 'changed' end) occurance,
#test:=`value` testvar
FROM
Table1
,(SELECT #test:='new') t
HAVING occurance='changed'
ORDER BY `Id`
See fiddle demo

Related

Find Values between two different columns in a table

table one
+----------------------+
|column A | Column B|
| 2 | 4 |
| 3 | 5 |
| 1 | 2 |
| 1 | 2 |
| 8 | 7 |
+----------------------+
Output
+-------+
|1 | 2 |
|1 | 2 |
+-------+
i want to print only the above output without COUNT, and any duplicate record example? please help
how about below where cluase
select * from t where columnA=1 and columnB=2
or
select columnA,columnB from t
group by columnA,columnB
having count(*)>1
or you can use exists
select t1.* from t t1 where exists
(select 1 from t t2 where t2.columnA=t1.columnA
and t2.columnB=t1.columnB group by columnA,columnB
having count(*)>1
)
You possibly want only those rows which are duplicate. If you don't have Window Functions available in your MySQL version, you can do the following:
SELECT
t.*
FROM your_table AS t
JOIN (SELECT columnA, columnB
FROM your_table
GROUP BY columnA, columnB
HAVING COUNT(*) > 1) AS dt
ON dt.columnA = t.columnA AND dt.columnB = t.columnB
Details: In a Derived table, we get all those combination of columnA and columnB which have more than one row(s) (HAVING COUNT(*) > 1).
Now, we simply join this result-set back to the main table, to get those rows only.
Note: This approach would not be needed if you want to fetch only these two columns. A simple Group By with Having would suffice, as suggested in other answer(s). However, if you have more columns in the table, and you will need to fetch all of them, and not just the columns (used to determine duplicates); you will need to use this approach.
You can use in operator with a grouped subquery as :
select *
from tab
where ( columnA, columnB) in
(
select columnA, count(columnA)
from tab
group by columnA
);
or use a self-join as :
select t1.columnA, t1.columnB
from tab t1
join
(
select columnA, count(columnA) as columnB
from tab
group by columnA
) t2
on ( t1.columnA = t2.columnA and t1.columnB = t2.columnB );
Rextester Demo
I would use EXISTS, if the table has primary column :
SELECT t.*
FROM table t
WHERE EXISTS (SELECT 1 FROM table t1 WHERE t1.col1 = t.col1 AND t1.col2 = t.col2 AND t1.pk <> t.pk);

Select duplicates while concatenating every one except the first

I am trying to write a query that will select all of the numbers in my table, but those numbers with duplicates i want to append something on the end that shows it as a duplicate. However I am not sure how to do this.
Here is an example of the table
TableA
ID Number
1 1
2 2
3 2
4 3
5 4
SELECT statement output would be like this.
Number
1
2
2-dup
3
4
Any insight on this would be appreciated.
if you mysql version didn't support window function. you can try to write a subquery to make row_number then use CASE WHEN to judgement rn > 1 then mark dup.
create table T (ID int, Number int);
INSERT INTO T VALUES (1,1);
INSERT INTO T VALUES (2,2);
INSERT INTO T VALUES (3,2);
INSERT INTO T VALUES (4,3);
INSERT INTO T VALUES (5,4);
Query 1:
select t1.id,
(CASE WHEN rn > 1 then CONCAT(Number,'-dup') ELSE Number END) Number
from (
SELECT *,(SELECT COUNT(*)
FROM T tt
where tt.Number = t1.Number and tt.id <= t1.id
) rn
FROM T t1
)t1
Results:
| id | Number |
|----|--------|
| 1 | 1 |
| 2 | 2 |
| 3 | 2-dup |
| 4 | 3 |
| 5 | 4 |
If you can use window function you can use row_number with window function to make rownumber by Number.
select t1.id,
(CASE WHEN rn > 1 then CONCAT(Number,'-dup') ELSE Number END) Number
from (
SELECT *,row_number() over(partition by Number order by id) rn
FROM T t1
)t1
sqlfiddle
I made a list of all the IDs that weren't dups (left join select) and then compared them to the entire list(case when):
select
case when a.id <> b.min_id then cast(a.Number as varchar(6)) + '-dup' else cast(a.Number as varchar(6)) end as Number
from table_a
left join (select MIN(b.id) min_id, Number from table_a b group by b.number)b on b.number = a.number
I did this in MS SQL 2016, hope it works for you.
This creates the table used:
insert into table_a (ID, Number)
select 1,1
union all
select 2,2
union all
select 3,2
union all
select 4,3
union all
select 5,4

Issue with a SELECT statement within a IN

I'm trying to select a bunch of rows from my first table depending of values from my second table.
To realize that, I came up with the following query :
SELECT *
FROM table2 t2
WHERE t2.id IN(
SELECT subquery.id
FROM
(
SELECT id
FROM table1 t1
WHERE (t1.property=10 AND t1.value=0)
) AS subquery
INNER JOIN
(
SELECT id
FROM table1 t1
WHERE (t1.property=20 AND i.value=1)
) AS subquery2
on subquery.id=subquery2.id
)
Depending of the property and value from table1, a specific list of id will be selected to be used as a condition for the final SELECT with the table2.
The subquery in itself is working, I tested it and I could retrieve the good id.
+------+
| id |
|------|
| 18 |
| 55 |
¦ ¦
Problem is, the IN isn't working, at the end of the final SELECT I retrieved all the rows from table2 instead of the ones respecting the condition of having the same id as the subquery retrieved earlier.
+------+------+---
| id | name |
|------|------|---
| 1 | xx |
| 2 | yy |
¦ ¦ ¦
So my question is :
Why is the subquery ignored in my IN statement and is there a way to bypass that problem ?
EDIT
Here is a SQLFiddle as requested, but strangely, the code I posted is working here but not for my database.
SELECT * FROM table2 t2
INNER JOIN
(SELECT
subquery.id
FROM
(SELECT
id
FROM
table1 t1
WHERE
(t1.property = 10 AND t1.value = 0)) AS subquery
INNER JOIN
(SELECT
id
FROM
table1 t1
WHERE
(t1.property = 20 AND i.value = 1)) AS subquery2 ON subquery.id = subquery2.id)Z ON Z.id=t2.id
You can try above code.
Hope this will help.
try like the following; if you are having any null values in the columnn you won't get the expected result.
common_id not in
(
select common_id from Table1
where common_id is not null
)
SQL "select where not in subquery" returns no results

MYSQL Updating row to maximum value of similar rows

I have a table like this in MYSQL:
ID | NAME | VALUE |
----------------------------
1 | Bob | 1 |
2 | Bob | 2 |
3 | Jack | 5 |
4 | Jack | 8 |
5 | Jack | 10 |
and I'm trying to update the VALUE column to the highest value of rows with same NAME. So the result should be:
ID | NAME | VALUE |
----------------------------
1 | Bob | 2 |
2 | Bob | 2 |
3 | Jack | 10 |
4 | Jack | 10 |
5 | Jack | 10 |
I managed to get the max value like this:
SELECT MAX(Value) max FROM `table` GROUP BY Name having count(*) >1 AND MAX(Value) != MIN(Value)
But can't figure out how to put it in my update
Update table set Value = (SELECT MAX(Value) max FROM `table` GROUP BY Name having count(*) >1 AND MAX(Value) != MIN(Value))
Doesn't work. I'd appreciate any help.
This is easier than other answers are making it.
UPDATE MyTable AS t1 INNER JOIN MyTable AS t2 USING (Name)
SET Value = GREATEST(t1.Value, t2.Value);
You don't have to find the largest value. You just have to join each row to the set of rows with the same name, and set the Value to the greater Value of the two joined rows. This is a no-op on some rows, but it will apply to every row in turn.
http://sqlfiddle.com/#!9/f79a3/1
UPDATE t1
INNER JOIN (SELECT name, MAX(`value`) max_value
FROM t1 GROUP BY name) t2
ON t1.name = t2.name
SET t1.value = t2.max_value;
Create a temporary table consisting of ID NAME and MAX VALUE as follows:
CREATE TEMP TABLE TABLE1 AS
(SELECT NAME,MAX(Value) value FROM `table` GROUP BY Name having count(*) >1
AND MAX(Value) != MIN(Value)
);
Use this temporary table to do your update as follows:
UPDATE
Table_A
SET
Table_A.value = Table_B.value
FROM
`table` AS Table_A
INNER JOIN TABLE1 AS Table_B
ON Table_A.NAME = Table_B.NAME
Also this code is somewhat of an approximation as i am not familiar with mysql but i am familiar with sql.
Let me know if this doesn't help.
Simple left join would do the trick.
Try this out and let me know in case of any queries.
select a.id,a.name,b.value
from
table a
left join
(select name,max(value) as value from table group by name) b
on a.name=b.name;
You may use this query. The table is joined with a subquery (table t2) that contains the results you want to update your table with:
UPDATE `table` t1,
(SELECT Name, MAX(Value) maxv, MIN(Value) minv
FROM `table`
GROUP BY Name
HAVING COUNT(*)>1 AND maxv != minv) t2
SET t1.Value = t2.maxv
WHERE t1.Name = t2.Name;
If you want to know how will the values be updated, you can first run an equivalent SELECT query:
SELECT t1.*, t2.maxv
FROM `table` t1,
(SELECT Name, MAX(Value) maxv, MIN(Value) minv
FROM `table`
GROUP BY Name
HAVING COUNT(*)>1 AND maxv != minv) t2
WHERE t1.Name = t2.Name;
This query will display all the fields of table, followed by the new value maxv. You can check the current value and the new value, and if it looks fine, you may run the UPDATE query.

Find duplicate records in table mysql

I have a table like the following:
| ID | Short Name | Long Name |
|----|------------|-----------|
| 1 | s1 | l2 |
| 2 | s1 | l2 |
| 3 | s1 | l2 |
| 4 | s5 | l6 |
| .. | ... | |
I want to get all records that share the same Short Name and Long Name. I need their shared short name, long name, and 3 duplicates' IDs. For this particular example, I want {s1, l2, 1,2,3}
This is a fairly simple problem to solve. Basically what you want to do is write a subquery that counts the number of rows that match on your specified field for each row in your query. I have included a few examples below.
Find all rows that are duplicates and match on both name fields
SELECT * FROM TableName WHERE (SELECT COUNT(*) FROM TableName AS T2 WHERE T2.ShortName = TableName.ShortName AND T2.LongName = TableName.LongName) > 1;
Find all rows that are duplicates and match on the short name
SELECT * FROM TableName WHERE (SELECT COUNT(*) FROM TableName AS T2 WHERE T2.ShortName = TableName.ShortName) > 1;
Find all rows that are duplicates and match on the long name
SELECT * FROM TableName WHERE (SELECT COUNT(*) FROM TableName AS T2 WHERE T2.LongName = TableName.LongName) > 1;
Simply use a a self join of your table and select those rows where the two names are equal and the ids differ:
SELECT *
FROM <table> t1, <table> t2
WHERE t1.id <> t2.id
AND t1.short_name = t2.short_name
AND t1.long_name = t2.long_name;
You can use exits to see if there are any other data exists with the same condition where ID is not same.
select t1.* from table_name t1
where exists (
select 1 from table_name t2
where
t1.ID <> t2.ID
and t1.`Short Name` = t2.`Short Name`
and t1.`Long Name` = t2.`Long Name`
);