Histogram using to data tables (SQL query) - mysql

I want to make a histogram of the number of comments per user in January 2019 (including the once that haven't commented)
The tables I'm working with look like this:
id
Name
1
Jose
2
Pedro
3
Juan
4
Sofia
user_id
Comment
Date
1
Hello
2018-10-02 11:00:03
3
Didn't Like it
2018-06-02 11:00:03
1
Not so bad
2018-10-22 11:00:03
2
Trash
2018-7-21 11:00:03
I think I'm overcomplicating it. But here is my try:
#Here I'm counting how much comments are per person that have commented.
CREATE TABLE aux AS
SELECT user_id, COUNT(user_id)
FROM Undostres
GROUP BY user_id;
#With the following code, I end up with a table with the missing values (ids that haven't commented)
CREATE TABLE Test AS
SELECT DISTINCT user_id +1
FROM aux
WHERE user_id + 1 NOT IN (SELECT DISTINCT user_id FROM aux);
ALTER TABLE Test RENAME COLUMN user_id +1 TO ;
INSERT INTO Undostres (user_id)
SELECT user_id FROM Test;
It returns an error when I try to rename user_id+1 with other name. So I can't keep going.
Any suggestions would be great!

I would do it this way:
CREATE TABLE aux AS
SELECT Users.user_id, COUNT(Undostres.user_id) AS count
FROM Users
LEFT OUTER JOIN Undostres USING (user_id)
GROUP BY Users.user_id;
I am assuming you have a table Users that enumerates all your users, whether they have made any comments or not. The LEFT OUTER JOIN helps in this case, because if there are no comments for a given user, the user is still part of the result, and the COUNT is 0.

Related

Ordering the results from a junction table based on values of the row its foreign key belongs to

I have three tables for a many-to-many: Authors, Authorships, Books. I would like to select rows from authorship and order it alphabetically according to the author this row belongs to.
Example:
-- Authors --
ID Name
1 Peter
2 Gregory
3 Daniel
-- Authorships--
ID AuthorId BookId
1 1 1
2 2 1
3 3 1
-- Books--
ID Name
1 Foobook
I would like to write a select statement that returns all rows from authorship belonging to a specific book then orders the result by author name.
So something like this:
SELECT * FROM Authorships WHERE BookId = 1 ORDER BY (Authors.Name???);
Except I need to order the result.
I understand how this question might look silly because of its workaround/inefficient nature, but I am working with a lot of legacy code and am not allowed to really change anything else.
Thank you.
This will work:
SELECT auth.* FROM Authorships auth, Authors au, Books bk WHERE auth.BookId = bk.ID and auth.AuthorId = au.ID ORDER BY au.Name
SQLFiddle Link:
SQLFiddle

mysql query that a user has a row for every experience id

I have a SQL problem. I have a table where a user gets a row for every experience they complete. The schema looks similar to this fiddle: http://sqlfiddle.com/#!2/5d6a87/4
I am trying to write a query that lists every user that has expid 1-5. So in my example it would list userids: 1,2, and 4. Since userid 3 does not have 5 rows, one for each experience that user shouldn't be listed.
What you would like to use is "group by"
the query would look like it:
select userid
from some_table
group by userid
having count(*)>=5
you can also be creative and force 5 different expeids by
select userid
from some_table
group by userid
having count(distinct expid)>=5
light reading about group by:
http://www.w3schools.com/sql/sql_groupby.asp
Good luck!
Try this:
SELECT id,userid,expid FROM
some_table
GROUP BY userid
HAVING count(*)>= 5
Result:
ID USERID EXPID
1 1 1
6 2 1
13 4 1
See result in SQL Fiddle.
You just need to add the having clause. Read more here.
Here
SELECT * FROM some_table GROUP BY UserID having count(*)>= 5;
They way I see it should be like this but your question is not 100% clear, since you said 5 rows for every ExpID.
SELECT * FROM some_table GROUP BY UserID, ExpID having count(*)>= 5;

Cartesian Product Single Table

I have a very simple MySQL table with three attributs, let's call it word_tbl
id | word | count
I want to combine each row with all rows in the table and sum the value in count.
The results should be saved in a new table, called cartesian_tbl.
In my opinion, the cartesian_tbl should look like this:
id | word1_id | word2_id | count
My Problem of understanding are the two word_ids which are both a Foreign Key of word_id.id.
Is my schema correct or is there a simpler solution to reach my target?
Thank you for your help!
New:
These 2 tables are only an example...
Here a little example how the combination should work
If "Hello" with id 2 has count 4 and "Example" with id 32 has count 5. The new Datarow should look like this
1, 2,32,9
#Francois T
count is only a number
What additional informations do you need?
INSERT INTO cartesian_tbl (word1_id, word2_id, count)
SELECT w1.id, w2.id, w1.count+w2.count
FROM word_tbl w1
JOIN word_tbl w2
Create a table with id auto_increment
And something like that :
but what do you want into count ?
insert into cartesian_tbl (world1_id,world2_id,count)
select word1.id, word2.id, count??? from word_tbl word1 , word_tbl word

find out count of comma based value in MySql

I have two tables.
Table Emp
id name
1 Ajay
2 Amol
3 Sanjay
4 Vijay
Table Sports
Sport_name Played by
Cricket ^2^,^3^,^4^
Football ^1^,^3^
Vollyball ^4^,^1^
Now I want to write a query which will give me output like
name No_of_sports_played
Ajay 2
Amol 1
Sanjay 2
Vijay 2
So what will be Mysql query for this?
I agree with the above answers/comments that you are not using a database for what a database is for, but here is how you could calculate your table from your current structure in case you have no control over that:
SELECT Emp.name, IF(Played_by IS NULL,0,COUNT(*)) as Num_Sports
FROM Emp
LEFT JOIN Sports
ON Sports.Played_by RLIKE CONCAT('[[:<:]]',Emp.id,'[[:>:]]')
GROUP BY Emp.name;
See it in action here.
UPDATE: added the IF(Played_by IS NULL,0,COUNT(*)) instead of COUNT(*). This means that if an employee doesn't play anything they'll have a 0 as their Num_Sports. See it here (I also added in those ^ characters and it still works.
What it does is joins the Emp table to the Sports table if it can find the Emp.id in the corresponding Played_by column.
For example, if we wanted to see what sports Ajay played (id=1), we could do:
SELECT *
FROM Emp, Sports
WHERE Sports.Played_by LIKE '%1%'
AND Emp.id=1;
The query I gave as my solution is basically the query above, with a GROUP BY Emp.name to perform it for each employee.
The one modification is the use of RLIKE instead of LIKE.
I use RLIKE '[[:<:]]employeeid[[:>:]]' instead of LIKE '%employeeid%. The [[:<:]] symbols just mean "make sure the employeeid you match is a whole word".
This prevents (e.g.) Emp.id 1 matching the 1 in the Played_by of 3,4,11,2.
You do not want to store your relationships in a column like that. Create this table:
CREATE TABLE player_sports (player_id INTEGER NOT NULL, sport_id INTEGER NOT NULL, PRIMARY KEY(player_id, sport_id));
This assumes you have an id column in your sports table. So now a player will have one record in player_sports for each sport they play.
Your final query will be:
SELECT p.name, COUNT(ps.player_id)
FROM players p, player_sports ps
WHERE ps.player_id = p.id
GROUP BY p.name;

Selecting most recent as part of group by (or other solution ...)

I've got a table where the columns that matter look like this:
username
source
description
My goal is to get the 10 most recent records where a user/source combination is unique. From the following data:
1 katie facebook loved it!
2 katie facebook it could have been better.
3 tom twitter less then 140
4 katie twitter Wowzers!
The query should return records 2,3 and 4 (assume higher IDs are more recent - the actual table uses a timestamp column).
My current solution 'works' but requires 1 select to generate the 10 records, then 1 select to get the proper description per row (so 11 selects to generate 10 records) ... I have to imagine there's a better way to go. That solution is:
SELECT max(id) as MAX_ID, username, source, topic
FROM events
GROUP BY source, username
ORDER BY MAX_ID desc;
It returns the proper ids, but the wrong descriptions so I can then select the proper descriptions by the record ID.
Untested, but you should be able to handle this with a join:
SELECT
fullEvent.id,
fullEvent.username,
fullEvent.source,
fullEvent.topic
FROM
events fullEvent JOIN
(
SELECT max(id) as MAX_ID, username, source
FROM events
GROUP BY source, username
) maxEvent ON maxEvent.MAX_ID = fullEvent.id
ORDER BY fullEvent.id desc;