MySql: Consolidating rows with matching records - mysql

My table has a list of users with Items associated to them. I hope to be able to consolidate the items field into a list or create another column if the row has a matching User/email.
I have the following structure with in the MySQL table:
╔═══════════╦═════════════╦═════════════╦═════════════╦═════════════╦════════════╗
║ ID ║ User_ID ║ Item ║ Date ║ User ║ Email ║
╠═══════════╬═════════════╬═════════════╬═════════════╬═════════════╬════════════╣
║ 1 ║ 1 ║ Laptop 1 ║ 30th Nov ║ John ║ J#test.com ║
║ 2 ║ 2 ║ Laptop 3 ║ 12th Nov ║ Emma ║ e#test.com ║
║ 3 ║ 2 ║ Camera 3 ║ 12th Nov ║ Emma ║ e#test.com ║
╚═══════════╩═════════════╩═════════════╩═════════════╩═════════════╩════════════╝
I am very new to SQL but i think i would need to use some type of transpose field to a column function?
Any help will be greatly appreciated
Thanks

I think you want group_concat(). Personally, I would use user_id, rather than user/email. or, perhaps all three together. Something like this:
select user_id, user, email, group_concat(item) as items
from table t
group by user_id, user, email;

Related

Inserting Output of COUNT Statement to Table with MySql.

I've been struggling to come up with a solution to the following problem.
I have two tables with the following structure.
member table:
╔═══════════╦═════════════╦═════════╗
║ member_no ║ member_type ║ team_no ║
╠═══════════╬═════════════╬═════════╣
║ CON123 ║ monthly ║ 12 ║
╠═══════════╬═════════════╬═════════╣
║ CON456 ║ monthly ║ 13 ║
╠═══════════╬═════════════╬═════════╣
║ CON789 ║ annual ║ 13 ║
╚═══════════╩═════════════╩═════════╝
team table:
╔═════════╦════════════╦══════════════╗
║ team_no ║ supervisor ║ member_count ║
╠═════════╬════════════╬══════════════╣
║ 12 ║ John ║ 1 ║
╠═════════╬════════════╬══════════════╣
║ 13 ║ Joe ║ 2 ║
╠═════════╬════════════╬══════════════╣
║ 14 ║ Allan ║ 0 ║
╚═════════╩════════════╩══════════════╝
What I would like to do is something like this when inserting values into the "team" table:
INSERT INTO team (team_no , supervisor , member_count)
VALUES ("13" , "Joe" , SELECT COUNT(team_no) FROM member WHERE team_no = "13");
Essentially, I would like the member_count column from the "team" table to be populated with the total number of members belonging to that team using the COUNT function on the member table.
I'd be really thankful if anyone can help me with this problem.
you can use an INSERT / SELECT using this sintax
INSERT INTO team (team_no , supervisor , member_count)
select "13" , "Joe" , COUNT(team_no)
FROM member
WHERE team_no = "13"
see mysql doc for more https://dev.mysql.com/doc/refman/5.7/en/insert-select.html
You can basically do your query with additional parentheses:
INSERT INTO team (team_no , supervisor , member_count)
VALUES (13 , 'Joe' , (SELECT COUNT(team_no) FROM member WHERE team_no = 13));
Subqueries require their own parentheses.
Don't use single or double quotes for numbers.
Admittedly, I would probably use insert . . . select, but this is the smallest change to your attempted query.

SQL My Sub Query is Loading Forever

Okay so basically I am trying to run a simple query with a subquery on phpmyadmin using mysql and it won't stop loading after I run it. The query is:
SELECT t.tagValue FROM tags t WHERE t.tagID IN (SELECT ua.tagID FROM user_taggedArtists ua WHERE ua.userID = 2);
I have ran the individual queries on their own without combining them together and they seem to do what I want, but when I mix them into a subquery form phpmyadmin just loads forever, like I am getting an infinite loop or something.
tags table looks like that:
╔═══════╦═════════════╗
║ tagID ║ tagValue ║
╠═══════╬═════════════╣
║ 1 ║ metal ║
║ 2 ║ alternative ║
║ 3 ║ pop ║
╚═══════╩═════════════╝
etc.
user_taggedArtists table looks like this:
╔════════╦══════════╦═══════╦═════╦═══════╦═══════╗
║ userID ║ artistID ║ tagID ║ day ║ month ║ year ║
╠════════╬══════════╬═══════╬═════╬═══════╬═══════╣
║ 2 ║ 52 ║ 1 ║ 1 ║ 4 ║ 2009 ║
║ 2 ║ 52 ║ 1 ║ 1 ║ 4 ║ 2009 ║
║ 2 ║ 52 ║ 1 ║ 1 ║ 4 ║ 2009 ║
╚════════╩══════════╩═══════╩═════╩═══════╩═══════╝
ect.
Not sure what I am doing wrong here and any help would be greatly appreciated.
Thank you!
Hard to say 'zatly, but "IN", generally, is slow. Try a JOIN and WHERE. I'm going to pretend we can join on tagID. You should have indexes on the join column(s). If not anything you do will perform poorly.
SELECT t.tagValue
FROM tags t
INNER JOIN user_taggedArtists ua ON
t.tagID = ua.tagID
WHERE ua.userID = 2

MySQL - Merge rows in table based on multiple criteria

I'd like to merge rows based on multiple criteria, essentially removing duplicates where I get to define what "duplicate" means. Here is an example table:
╔═════╦═══════╦═════╦═══════╗
║ id* ║ name ║ age ║ grade ║
╠═════╬═══════╬═════╬═══════╣
║ 1 ║ John ║ 11 ║ 5 ║
║ 2 ║ John ║ 11 ║ 5 ║
║ 3 ║ John ║ 11 ║ 6 ║
║ 4 ║ Sam ║ 14 ║ 7 ║
║ 5 ║ Sam ║ 14 ║ 7 ║
╚═════╩═══════╩═════╩═══════╝
In my example, let's say I want to merge on name and age but ignore grade. The result should be:
╔═════╦═══════╦═════╦═══════╗
║ id* ║ name ║ age ║ grade ║
╠═════╬═══════╬═════╬═══════╣
║ 1 ║ John ║ 11 ║ 5 ║
║ 3 ║ John ║ 11 ║ 6 ║
║ 4 ║ Sam ║ 14 ║ 7 ║
╚═════╩═══════╩═════╩═══════╝
I don't particularly care if the id column is updated to be incremental, but I suppose that would be nice.
Can I do this in MySQL?
My suggestion, based on my above comment.
SELECT distinct name, age, grade
into tempTable
from theTable
This will ignore the IDs and give you only a distinct dump, and into a new table.
Then you can either drop the old and, and rename the new one. Or truncate the old one, and dump this back in.
You could just delete the duplicates in place like this:
delete test
from test
inner join (
select name, age, grade, min(id) as minid, count(*)
from test
group by name, age, grade
having count(*) > 1
) main on test.id = main.minid;
Example: http://sqlfiddle.com/#!9/f1a38/1

SSRS non-grouped data in the middle of grouped data in table

I'm not sure if I worded this properly. It's a lot easier to show. So without doing a subreport, is there any way to have the non-grouped data inside of grouped data.
╔════╦══════════════╦══════════════╦════════════╗
║ ID ║ Cars ║ Name ║ Date ║
╠════╬══════════════╬══════════════╬════════════╣
║ 1 ║ 2011 Chevy ║ John D ║ 1/1/2013 ║
║ ║ 2012 Ford ║ ║ ║
║ 2 ║ 2010 Pontiac ║ Jane D ║ 1/1/2012 ║
║ 3 ║ 1969 Chevy ║ Bob H ║ 12/1/2011 ║
║ ║ 1930 Ford ║ ║ ║
╚════╩══════════════╩══════════════╩════════════╝
Cars is not grouped. So there is 1:N relationship there with all the other data.
What I know you can do and have done is have the "Cars" all the way to the right and have it be ID, Name, Date, Cars but I cant seem how to get the cars in the middle of all of the grouped data columns. I know a subreport is "possible" but wondered if I am just missing the obvious
It's a hack, but I do it all the time:
You can embed a table in the Cars cell. You just need 1 Details cell on your embedded table (get rid of the headers and the extra columns that are auto added), and have it list your cars. It will only list the cars that are related to the value in column 1 on each row of the parent table, and should probably end up looking like your example above.

Update a table by inserting a count of foreign key from another table

I have two tables:
╔════════════════╗ ╔════════════════╗
║ ITEM ║ ║ ITEM_TRACK ║
╠════════════════╣ ╠════════════════╣
║ ID ║ ║ ID ║
║ GUID ║ ║ ITEM_GUID ║
║ COUNT1 ║ ║ CONTEXT ║
║ ENDDATE ║ ║ ║
╚════════════════╝ ╚════════════════╝
╔═════╦══════╦════════╗ ╔═════╦═══════════╦══════════╗
║ ID ║ GUID ║ COUNT1 ║ ║ ID ║ ITEM_GUID ║ CONTEXT ║
╠═════╬══════╬════════╣ ╠═════╬═══════════╬══════════╣
║ 1 ║ aaa ║ ║ ║ 1 ║ abc ║ ITEM ║
║ 2 ║ bbb ║ ║ ║ 2 ║ aaa ║ PAGE ║
║ 3 ║ ccc ║ ║ ║ 3 ║ bbb ║ ITEM ║
║ 4 ║ abc ║ ║ ║ 4 ║ ccc ║ ITEM ║
╚═════╩══════╩════════╝ ║ 5 ║ abc ║ ITEM ║
║ 6 ║ aaa ║ ITEM ║
║ 7 ║ abc ║ ITEM ║
║ 8 ║ ccc ║ PAGE ║
╚═════╩═══════════╩══════════╝
What I'm trying to do is fill in the COUNT1 column in ITEM with the count of the number of times ITEM_GUID appears in ITEM_TRACK for all ITEM.GUIDs where ENDDATE is still in the future. I need to do this once an hour for all GUIDS in ITEM.
I can get the counts I need easily
SELECT ITEM_GUID, COUNT(*) from ITEM_TRACK GROUP BY ITEM_GUID;
What I don't know how to do is, how do I merge this with an INSERT INTO statement to automatically update all the items in the items table with the count based on their ENDDATE?
UPDATE:
I have a working solution based on Aquillo's answer:
UPDATE ITEM a
SET COUNT1 = (SELECT COUNT(*) AS total FROM ITEM_TRACK b WHERE b.item_guid=a.guid);
Is there any other way to do this without a subquery?
You can insert from a select like this:
INSERT INTO myTable (foreignKey, countColumn) VALUES
SELECT ITEM_GUID, COUNT(*) from ITEM_TRACK GROUP BY ITEM_GUID;
In case you want to update, try something like this:
UPDATE from SELECT using SQL Server
If you use INSERT INTO you'll put additional rows in your ITEM table, not update the existing ones. If this is what you meant then that's great, but if you want to update the existing ones, you'll need to use update. You do this by joining the table you want to update with the table you want to update from. However, in your case you want to update from an aggregation and so you need to create a table with the aggregated values. Try this:
UPDATE ITEM SET Count1 = temp.total
FROM Item
INNER JOIN (
SELECT ITEM_GUID, COUNT(*) AS total
FROM ITEM_TRACK
GROUP BY ID) AS temp
ON Item.GUID = temp.ITEM_GUID
WHERE ENDDATE > NOW()
I've tried this on SQL Server (using GETDATE() instead of NOW()) to double check and it worked, I think it should work on MYSQL.