How to compare and change values in MYSQL - mysql

My table looks like:
[Number] [Value1]
1234567 8
1234567C 7
9876543 1
9876543C 2
5555555 3
5555555C 3
I want to search the entries for same values in the first column (except the "C" in the end of the number) and set the higher value in the second column to the lower one.
There are always only two same values (one with "C") and some pairs have same values in the second column and some have different.
The result of the query should be:
Number Value1
1234567 7
1234567C 7
9876543 1
9876543C 1
5555555 3
5555555C 3

The following is not an ideal solution but should do what you want:
update yourTable
set value1 = (
select min(value1) from (
select * from yourTable
) as x
where yourTable.number = x.number + 'C');
I have tested it with this in mysql workbench:
create table yourTable(number varchar (10),value1 int);
insert into yourTable Values('1234567',8);
insert into yourTable Values('1234567C',7);
insert into yourTable Values('9876543',1);
insert into yourTable Values('9876543C',2);
insert into yourTable Values('5555555',3);
insert into yourTable Values('5555555C',3);
insert into yourTable Values('55555556',10);
insert into yourTable Values('55555556C',2);
Then select * from yourTable;will return:
1234567 8
1234567C 7
9876543 1
9876543C 2
5555555 3
5555555C 3
55555556 10
55555556C 2
After the update select * from yourTable; will return:
1234567 7
1234567C 7
9876543 1
9876543C 1
5555555 3
5555555C 3
55555556 2
55555556C 2
Hope that is what you wanted :)

Actually, you don't need any checking, since there are only 2 values (and thus the query is even simpler):
UPDATE
table
SET
Value1 =
(
SELECT
MAX(Value1)
FROM
table t
WHERE
table.Number = t.Number
OR table.Number = t.Number + 'C'
)
WHERE
RIGHT(Number, 1) != 'C'

Related

MySQL: How to add a column for original_id?

I want to add a column original_id to existing table, for example table_1:
sub_id
next_sub_id
2
4
4
6
6
null
8
10
10
null
to table_2 as sub_id = 4 or sub_id = 6 belongs to the first one that sub_id = 2
and sub_id = 10 belongs to sub_id = 8
sub_id
next_sub_id
original_id
2
4
2
4
6
2
6
null
2
8
10
8
10
null
8
How can I query under MySQL? Thanks!
You can check this link for more detail information
sameple is like this
ALTER TABLE table
ADD [COLUMN] column_name column_definition [FIRST|AFTER existing_column];
then you can update the value in the new column
sample is like this
UPDATE [LOW_PRIORITY] [IGNORE] table_name
SET
column_name1 = expr1,
column_name2 = expr2,
...
[WHERE
condition];
You can use a recursive CTE for this:
with recursive cte as (
select sub_id, next_sub_id, sub_id as original_id, 1 as lev
from t
where not exists (select 1 from t t2 where t2.next_sub_id = t.sub_id)
union all
select t.sub_id, t.next_sub_id, cte.original_id, lev + 1
from t join
cte
on cte.next_sub_id = t.sub_id
)
select *
from cte
order by sub_id;
Here is a db<>fiddle.

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

Need MySql query that should return result by ordering values in particular field

Need MySql query that should return result by ordering values in particular field.
From below my result set should contain order like parent_id (1,4,6) should come first parent_id(2,3,7) come next and other should come last.
d data parent_id
----------------------
1 a1 1
2 abc 3
3 abcd 4
4 xyz 2
5 zxyy 6
2 abc 8
3 abcd 9
4 xyz 2
5 zxyy 15
Use a CASE expression in your ORDER BY clause:
SELECT d, data, parent_id
FROM yourTable
ORDER BY CASE WHEN parent_id IN (1, 4, 6) THEN 1
WHEN parent_id IN (2, 3, 7) THEN 2
ELSE 3 END,
parent_id
Follow the link below for a running demo:
SQLFiddle
Use below mentioned query
SELECT d, data, parent_id FROM table_name ORDER BY FIELD(parent_id,1,4,6,2,3,7);

Update a column of a table with the count of other column in the same table in a MySQL server

I have a table like this:
recordid customerid product id count
1 2 12 3
2 4 10 1
3 2 3 3
4 3 12 2
5 3 10 2
6 2 7 3
7 5 3 1
8 ....
9 ....
I want an update query that will count the no of occurrence of each customer id and update the count column which will initially be empty.
the end result should be like above
The column names are dummy, my actual table is different.
It has data in millions of rows.The query should be speedy
I tried the query but it gets stuck...
update tablename, (select count(recordid) as count,customerid from tablename group by customerid) as temp set count=temp.count where customerid=temp.customerid
You can use JOIN in UPDATE.
Try this:
UPDATE TableName A
JOIN
(SELECT customerid,Count(customerid) as cnt
FROM TableName
GROUP BY customerid) as B ON A.customerid= B.customerid
SET A.count = B.cnt
This doesn’t see right:
update tablename, (select count(recordid) as count,customerid from tablename group by customerid) as temp set count=temp.count where customerid=temp.customerid
Why is there a comma after update tablename like this:
update tablename,
I am also reformatting for readability:
UPDATE tablename (
SELECT count(recordid) AS count, customerid
FROM tablename GROUP BY customerid
) as temp
SET count=temp.count
WHERE customerid = temp.customerid

SQL statement for querying with multiple conditions including 3 most recent dates

I need help in finding the rows that correspond to the most recent date, the next most recent and the one after that, where some condition ABC is "Y" and group it by a column name XYZ ASC but XYZ can appear multiple times. So, say XYZ is 50, then for the rows in the three years, the XYZ will be 50. I have the following code that executes but returns only two rows out of thousands which is impossible. I tried executing just the date condition but it returned dates that were less than or equal to MAX(DATE)-3 as well. Don't know where I am going wrong.
select * from money.cash where DATE =(
select
MAX(DATE)
from
money.cash
where
DATE > (select MAX(DATE)-3 from money.cash)
)
GROUP BY XYZ ASC
having ABC = "Y";
The structure of the table is as follows (only a schematic, not the real thing).
Comp_ID DATE XYZ ABC $$$$ ....
1 2012-1-1 10 Y SOME-AMOUNT
2 2011-1-1 10 Y
3 2006-1-1 10 Y
4 2011-1-1 20 Y
5 2002-1-1 20 Y
6 2000-1-1 20 Y
7 1998-1-1 20 Y
The desired o/p would be the first three rows for XYZ=10 in ascending order and the most recent 3 dates for XYZ=20.
LAST AND IMPORTANT-This table's values keeps changing as new data comes in. So, the o/p(which will be in a new table) must reflect the dynamics in the 1st/original/above TABLE.
MySQL doesn't have functionallity that is friendly to greatest-n-per-group queries.
One option would be...
- Find the MAX(Date) per group (XYZ)
- Then use that result to find the MAX(Date) of all records before that date
- Then do it again for all records before that date
It's really innefficient, but MySQL hasn't got the functionality required to do this efficiently. Sorry...
CREATE TABLE yourTable
(
comp_id INT,
myDate DATE,
xyz INT,
abc VARCHAR(1)
)
;
INSERT INTO yourTable SELECT 1, '2012-01-01', 10, 'Y';
INSERT INTO yourTable SELECT 2, '2011-01-01', 10, 'Y';
INSERT INTO yourTable SELECT 3, '2006-01-01', 10, 'Y';
INSERT INTO yourTable SELECT 4, '2011-01-01', 20, 'Y';
INSERT INTO yourTable SELECT 5, '2002-01-01', 20, 'Y';
INSERT INTO yourTable SELECT 6, '2000-01-01', 20, 'Y';
INSERT INTO yourTable SELECT 7, '1998-01-01', 20, 'Y';
SELECT
yourTable.*
FROM
(
SELECT
lookup.XYZ,
COALESCE(MAX(yourTable.myDate), lookup.MaxDate) AS MaxDate
FROM
(
SELECT
lookup.XYZ,
COALESCE(MAX(yourTable.myDate), lookup.MaxDate) AS MaxDate
FROM
(
SELECT
yourTable.XYZ,
MAX(yourTable.myDate) AS MaxDate
FROM
yourTable
WHERE
yourTable.ABC = 'Y'
GROUP BY
yourTable.XYZ
)
AS lookup
LEFT JOIN
yourTable
ON yourTable.XYZ = lookup.XYZ
AND yourTable.myDate < lookup.MaxDate
AND yourTable.ABC = 'Y'
GROUP BY
lookup.XYZ,
lookup.MaxDate
)
AS lookup
LEFT JOIN
yourTable
ON yourTable.XYZ = lookup.XYZ
AND yourTable.myDate < lookup.MaxDate
AND yourTable.ABC = 'Y'
GROUP BY
lookup.XYZ,
lookup.MaxDate
)
AS lookup
INNER JOIN
yourTable
ON yourTable.XYZ = lookup.XYZ
AND yourTable.myDate >= lookup.MaxDate
WHERE
yourTable.ABC = 'Y'
ORDER BY
yourTable.comp_id
;
DROP TABLE yourTable;
There are other options, but they're all a bit hacky. Search SO for greatest-n-per-group mysql.
My results using your example data:
Comp_ID | DATE | XYZ | ABC
------------------------------
1 | 2012-1-1 | 10 | Y
2 | 2011-1-1 | 10 | Y
3 | 2006-1-1 | 10 | Y
4 | 2011-1-1 | 20 | Y
5 | 2002-1-1 | 20 | Y
6 | 2000-1-1 | 20 | Y
Here's another way, hopefully more efficient than Dems' answer.
Test it with an index on (abc, xyz, date):
SELECT m.xyz, m.date --- for all columns: SELECT m.*
FROM
( SELECT DISTINCT xyz
FROM money.cash
WHERE abc = 'Y'
) AS dm
JOIN
money.cash AS m
ON m.abc = 'Y'
AND m.xyz = dm.xyz
AND m.date >= COALESCE(
( SELECT im.date
FROM money.cash AS im
WHERE im.abc = 'Y'
AND im.xyz = dm.xyz
ORDER BY im.date DESC
LIMIT 1
OFFSET 2 --- to get 3 latest rows per xyz
), DATE('1000-01-01') ) ;
If you have more than rows with same (abc, xyz, date), the query may return more than 3 rows per xyz (all tied in 3rd place will all be shown).