MYSQL query to Update the field if found duplicates? - mysql

Here is my problem. I got a table Meaning
ID - Meaning
1 - red car
2 - cat man
3 - red car
4 - ontime
5 - red car
....
I want to make the colum Meaning become Unique. So i want to build a query to found all the duplicates & for each of duplicate, the system should append [number] to make the cell become unique.
So after running that query, the result should be:
ID - Meaning
1 - red car
2 - cat man
3 - red car [2]
4 - ontime
5 - red car [3]
....
The table is pretty long about 100K rows. The query could be similar to this query
Update Table Meaning set meaning=concat(meaning,"1")
where meaning in (select meaning from Meaning group by meaning having count(meaning>1)
So what is the query for solving the problem?
Seem we have to use set variable to check each row?

step 1: create temporary table
CREATE TABLE TMP (id int, meaning varchar (2));
step 2: prepare query and insert into temporary table
insert into tmp
SELECT id,
CASE WHEN cnt =0 theN meaning ELSE concat(meaning,'[',cnt+1,']') END AS meaning
FROM
(
SELECT t1.id, t1.meaning, (
SELECT COUNT( t.id )
FROM test t
where t.meaning=t1.meaning
and t.id<t1.id
) as cnt
FROM test t1
)TMP
step 3
truncate table test
step 4: migrate to original
insert into test select * from tmp

SELECT x.*
, CONCAT(x.meaning,CASE WHEN COUNT(*) = 1 THEN '' ELSE COUNT(*) END) meaning
FROM meanings
x JOIN meanings
y ON y.meaning = x.meaning
AND y.id <= x.id
GROUP
BY id;

Related

SQL to club records in sequence

I have data in MySQL table, my data looks like
Key, value
A 1
A 2
A 3
A 6
A 7
A 8
A 9
B 1
B 2
and I want to group it based on the continuous sequence. Data is sorted in the table.
Key, min, max
A 1 3
A 6 9
B 1 2
I tried googling it but could find any solution to it. Can someone please help me with this.
This is way easier with a modern DBMS that support window functions, but you can find the upper bounds by checking that there is no successor. In the same way you can find the lower bounds via absence of a predecessor. By combining the lowest upper bound for each lower bound we get the intervals.
select low.keyx, low.valx, min(high.valx)
from (
select t1.keyx, t1.valx from t t1
where not exists (
select 1 from t t2
where t1.keyx = t2.keyx
and t1.valx = t2.valx + 1
)
) as low
join (
select t3.keyx, t3.valx from t t3
where not exists (
select 1 from t t4
where t3.keyx = t4.keyx
and t3.valx = t4.valx - 1
)
) as high
on low.keyx = high.keyx
and low.valx <= high.valx
group by low.keyx, low.valx;
I changed your identifiers since value is a reserved world.
Using a window function is way more compact and efficient. If at all possible, consider upgrading to MySQL 8+, it is superior to 5.7 in so many aspects.
We can create a group by looking at the difference between valx and an enumeration of the vals, if there is a gap the difference increases. Then, we simply pick min and max for each group:
select keyx, min(valx), max(valx)
from (
select keyx, valx
, valx - row_number() over (partition by keyx order by valx) as grp
from t
) as tt
group by keyx, grp;
Fiddle

Only update a single row in a query based on non-unique parameters?

I have a big table with duplicate keys that I am trying to connect to smaller table that has unique keys. I know for a fact there will not matches for everything. I only want a match from my smaller table to update a single row in the bigger table and then to move onto the next smaller table row for the next update. I need it like this because I am trying to create unique id's in the larger table as each row represents a real world product which has it's own heiarchy of real world objects.
So for example,
bigtable
barcodeSnippet t_stamp workId parentCase newId
aaaa time1 1 1 NULL
aaaa time1 1 1 NULL
aaaa time1 1 1 NULL
and my small table might have this
smalltable
id barcodeSnippet t_stamp workId parentCase
1 aaaa time1 1 1
2 aaaa time1 1 1
the end result I want in my bigtable is
bigtable
barcodeSnippet t_stamp workId parentCase newId
aaaa time1 1 1 1
aaaa time1 1 1 2
aaaa time1 1 1 NULL
where I only mached once per row, and was left over with a NULL since I had 3 rows in the big table and two matches in my smaller one.
My current query
UPDATE bigtable as bt
JOIN smallTable as st ON (bt.barcodeSnippet = b.barcodeSnippet AND
bt.parentCase= st.parentCase and bt.t_stamp = st.t_stamp and bt.workId =
st.workId)
SET bt.bottlesId = st.id;
does not work, and I don't see it's possible to use the LIMIT in a UPDATE for MySQL. I have seen other answers in MS SQL where you can use TOP 1, perhaps where newId IS NULL, but again I am using MySQL here.
I am thinking I might need to use a Stored Procedure/Cursor approach but even with that it seems like I will run into the issue of having to run an update statement and then I am back at square 1.
Any ideas? Using MySQL 5.6.
EDIT: Think I have a decent solution. I just updated with my query so I do have duplicates. However, now I added a row number column. I plan to join the table on itself and update it if the row number is < the row number, therefore I keep the top ID and can turn the others to null, which is suitable.
Something like this
UPDATE bigtable tb
JOIN bigtable tb2 ON tb.newId = tb2.newId
SET tb.newId = NULL
WHERE tb.rowNumber < tb2.rowNumber;
You use the auto_incremented id column with the superglobal $_GET:
1.php
<?php $var = $row["id"]; ?>
Something
Then in your 2.php
<?php $id = $_GET["id"];
$sql = "SELECT * FROM table WHERE id='$id';";
Of course you need to use prepared statements

How to do this query against MySQL database table?

I was given a task to show the CPU usage trend as part of a building process which also do regression test.
Each individual test case run has a record in the table RegrCaseResult. The RegrCaseResult table looks something like this:
id projectName ProjectType returnCode startTime endTime totalMetrics
1 'first' 'someType' 16 'someTime' 'someOtherTime' 222
The RegrCaseResult.totalMetrics is a special key which links to another table called ThreadMetrics through ThreadMetrics.id.
Here is how ThreadMetrics will look like:
id componentType componentName cpuTime linkId
1 'Job Totals' 'Job Totals' 'totalTime' 34223
2 'parser1' 'parser1' 'time1' null
3 'parser2' 'generator1' 'time2' null
4 'generator1' 'generator1' 'time3' null
------------------------------------------------------
5 'Job Totals' 'Jot Totals' 'totalTime' 9899
...
The rows with the compnentName 'Job Totals' is what the totalMetrics from RegrCaseResult table will link to and the 'totalTime' is what I am really want to get given a certain projectType. The 'Job Totals' is actually a summation of the other records - in the above example, the summation of time1 through time3. The linkId at the end of table ThreadMetrics can link back to RegrCaseResult.id.
The requirements also states I should have a way to enforce the condition which only includes those projects which have a consistent return code during certain period. That's where my initial question comes from as follows:
I created the following simple table to show what I am trying to achieve:
id projectName returnCode
1 'first' 16
2 'second' 16
3 'third' 8
4 'first' 16
5 'second' 8
6 'first' 16
Basically I want to get all the projects which have a consistent returnCode no matter what the returnCode values are. In the above sample, I should only get one project which is "first". I think this would be simple but I am bad when it comes to database. Any help would be great.
I tried my best to make it clear. Hope I have achieved my goal.
Here is an easy way:
select projectname
from table t
group by projectname
having min(returncode) = max(returncode);
If the min() and max() values are the same, then all the values are the same (unless you have NULL values).
EDIT:
To keep 'third' out, you need some other rule, such as having more than one return code. So, you can do this:
select projectname
from table t
group by projectname
having min(returncode) = max(returncode) and count(*) > 1;
select projectName from projects
group by projectName having count(distinct(returnCode)) = 1)
This would also return projects which has only one entry.
How do you want to handle them?
Working example: http://www.sqlfiddle.com/#!2/e7338/8
This should do it:
SELECT COUNT(ProjectName) AS numCount, ProjectName FROM (
SELECT ProjectName FROM Foo
GROUP BY ProjectName, ReturnCode
) AS Inside
GROUP BY Inside.ProjectName
HAVING numCount = 1
This groups all the ProjectNames by their names and return codes, then selects those that only have a single return code listed.
SQLFiddle Link: http://sqlfiddle.com/#!2/c52b6/11/0
You can try something like this with Not Exists:
Select Distinct ProjectName
From Table A
Where Not Exists
(
Select 1
From Table B
Where B.ProjectName = A.ProjectName
And B.ReturnCode <> A.ReturnCode
)
I'm not sure exactly what you're selecting, so you can change the Select statement to what you need.

mySQL count occurances of value on multiple fields. How?

I have a table with 5 fields. Each field can store a number from 1 - 59.
Similar to countif in Excel, how do I count the number of times a number from 1 - 59 shows up in all 5 fields?
Here's an example for the count of occurances for the number 1 in all five fields:
SELECT SUM(pick_1 = 1 OR pick_2 = 1 OR pick_3 = 1 OR pick_4 = 1 OR pick_5 = 1) AS total_count_1
FROM tbldraw
Hopefully I made sense.
There was an answer here that had a solution. I think this is just a variation.
Step1: Create a numbers table (1 field, called id, 59 records (values 1 -59))
Step2:
SELECT numbers_table.number as number
, COUNT(tbldraw.pk_record)
FROM numbers_table
LEFT JOIN tbldraw
ON numbers_table.number = tbldraw.pick_1
OR numbers_table.number = tbldraw.pick_2
OR numbers_table.number = tbldraw.pick_3
OR numbers_table.number = tbldraw.pick_4
OR numbers_table.number = tbldraw.pick_5
GROUP BY number
ORDER BY number
How about a two step process? Assuming a table called summary_table ( int id, int ttl), for each number you care about...
insert into summary_table values (1,
(select count(*)
from table
where field1 = 1 or field2 = 1 or field3 = 1 or field4 = 1 or field5 = 1))
do that 59 times, once for each value. You can use a loop in most cases. Then you can select from the summary_table
select *
from summary_table
order by id
That will do it. I leave the coversion of this SQL into a stored procedure for those that know what database is in use.
The ALL() function, which returns true if the preceding operator is true for all parameters, makes the query particularly elegant and succinct.
To find the count a particular number (eg 3):
select count(*)
from tbldraw
where 3 = all (pick_1, pick_2, pick_3, pick_4, pick_5)
To find the count of all such numbers:
select pick_1, count(*)
from tbldraw
where pick_1 = all (pick_2, pick_3, pick_4, pick_5)
group by pick_1

MySQL How To Use Main Select Value As Subquery Argument?

I am trying to construct a query that is a bit more complicated than anything I've done in my limited experience with databases.
TABLE:
id - data - type - data3
1 - hello - 1 - 1
2 - goodbye - 1 - 1
3 - goodbye - 1 - 2
4 - goodbye - 2 - 1
5 - hello - 2 - 1
The goal is to do 4 things:
GROUP the results by "data", but only return one result/row of each
data type.
COUNT the total number of each "data GROUP and return this number.
Do this for both "type"=1 and "type"=2, though I only need each
"data" GROUP item once.
the ability to sort results based on each SELECT item.
So the final result returned should be (sorry to be confusing!):
data, COUNT(data["type"]=1), COUNT(data["type"]=2 AND data["data"] = data)
So, for the sample table above, desired results would be:
loop 1 - hello, 2, 1
loop 2 - goodbye, 3, 1
Then, ideally, I could sort results by any of these.
This is the query I was trying to construct before resorting to posting this, I don't think it's even close to being correct, but it may help illustrate what I'm trying to achieve a bit better:
SELECT
(
SELECT `clicks_network_subid_data`, COUNT(*)
FROM track_clicks
WHERE `clicks_campaign_id`='$id' AND `clicks_click_type` = '1'
) AS keywords,
(
SELECT COUNT(*)
FROM track_clicks
WHERE `clicks_campaign_id`='$id' AND `clicks_click_type` = '2' AND `clicks_network_subid_data` = keywords.clicks_network_subid_data
) AS offer_clicks
GROUP BY keywords.clicks_network_subid_data
ORDER BY keywords.COUNT(*) DESC
I also need to do a JOIN on another table to grab one more piece of data, but I think I can handle that once I get this part figured out.
You can use an IF-function for this
SELECT `clicks_network_subid_data`,
SUM(IF(clicks_click_type` == '1',1,0)) as keywords,
SUM(IF(clicks_click_type` == '2',1,0)) as offer_clicks,
FROM track_clicks
GROUP BY clicks_network_subid_data
ORDER BY clicks_network_subid_data DESC
You can do this using GROUP BY:
SELECT data, COUNT(*) AS cnt FROM `table` GROUP BY type ORDER BY COUNT(*)
Ordering might become a little slow, as this is a calculated field, but if you don't have a large result set then you are good to go.
First of all your question is bit not clear , However, check this query . what I suspect is that you need count results in columns (single ) instead of rows .
select * , count(type_one) as t1_count , count(type_two) as t2_count from (
select data,if(tmp.type=1,1,0) as type_one, if(tmp.type=2,1,0) as type_two from (
select 1 as id , 'hello' as data , 1 as type , 1 as data3 union
select 2 as id , 'goodbye' as data , 1 as type , 1 as data3 union
select 3 as id , 'goodbye' as data , 1 as type , 2 as data3 union
select 4 as id , 'goodbye' as data , 2 as type , 1 as data3 union
select 5 as id , 'hello' as data , 2 as type , 1 as data3
) tmp
) tmp2
group by tmp2.type_one ;
let me know if this works for you
cheers :)