Merge the rows and give me the total count - mysql

I want to count how many unique games a user have been played. Here's how the current SQL query looks like:
SELECT COUNT(DISTINCT d.id_game) AS c
FROM discord AS d
JOIN discord_games AS dg
ON d.id_game = dg.id
WHERE d.id_user = '1'
AND d.id_game != '0'
GROUP BY d.id_game
ORDER BY dg.data_name ASC
And here's now the database looks like:
CREATE TABLE IF NOT EXISTS `discord` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_user` int(11) NOT NULL,
`id_channel` varchar(50) NOT NULL,
`id_game` int(11) NOT NULL,
`data_muted_server` tinyint(4) NOT NULL,
`data_muted_self` tinyint(4) NOT NULL,
`data_deafen_server` tinyint(4) NOT NULL,
`data_deafen_self` tinyint(4) NOT NULL,
`data_suppressed` tinyint(4) NOT NULL,
`data_status` varchar(10) NOT NULL,
`datetime_logged` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
)
CREATE TABLE IF NOT EXISTS `discord_games` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`data_name` varchar(50) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
)
CREATE TABLE IF NOT EXISTS `discord_users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`data_id` text NOT NULL,
`data_name` varchar(50) NOT NULL,
`data_avatar` text,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
)
The SQL query counts correctly but it only counts 1 per row.
Example of how I'm thinking. If the user with the ID 1 have played the same game 24 times (for an example Battlefield 3) it will return 1 played game. If the same user plays another game 37 times, it will return 2 played games and so on.
SUM(DISTINCT ... doesn't work since it only replace 1 with the game ID.
How can I sum the rows so it displays the number 2 instead of 2 rows?

You could just remove the group by property and count the distinct games played. It will return the number of distinct gamesp layed by the user 1
SELECT COUNT(DISTINCT d.id_game) AS c
FROM discord AS d
JOIN discord_games AS dg
ON d.id_game = dg.id
WHERE d.id_user = '1'
AND d.id_game != '0'
ORDER BY dg.data_name ASC

Related

multi field Group by in mysql with 0 result

let suppose I have the following tables
Listing Table
`listing` (
`fact_listing_id` INT(11) NOT NULL,
`region_id` INT(11) NOT NULL,
`created_at_date_id` INT(11) NOT NULL,
`category_id` INT(11) NOT NULL,
PRIMARY KEY (`fact_listing_id`),
)
Dim Category Table
`dim_category` (
`category_id` INT(11) NOT NULL,
`category_name` VARCHAR(100) NOT NULL,
`parent_category_id` INT(11) NULL,
`parent_category_name` VARCHAR(100) NULL,
PRIMARY KEY (`category_id`),
)
Dim Region Table
`dim_region` (
`region_id` INT(11) NOT NULL,
`region_name` VARCHAR(80) DEFAULT NULL,
PRIMARY KEY (`region_id`)
)
Dim Date Table
`dim_date` (
`date_id` INT(11) NOT NULL, -- date_key
`date` DATE,
`month` INT(11) NULL,
`day_of_month` INT(11) NULL,
`day_of_week` INT(11) NULL,
`week_of_month` INT(11) NULL,
`year` INT(11) NULL,
`quarter` INT(11) NULL,
PRIMARY KEY (`date_id`)
)
and now I want have a query to get count the number of listings in each category, in each region and each day by grouping on three fields, 'region_id','category_id' and 'date_id'
for one dimension, I mean grouping on one dimension it works correctly with the following query
select
count(fl.fact_listing_id) as Count
, dr.region_id
from fact_listing fl
right JOIN dim_region dr on fl.region_id = dr.region_id
group by
dr.region_id;
BUT when I try the following query the results aren't as I expecting
select
count(fl.fact_listing_id) as Count
, dr.region_id
, dc.category_id
, fl.created_at_date_id
from fact_listing fl
right JOIN dim_region dr on fl.region_id = dr.region_id
right JOIN dim_category dc on fl.category_id = dc.category_id
right JOIN dim_date dd on fl.created_at_date_id = dd.date_id
group by
fl.created_at_date_id
,dr.region_id
,dc.category_id;
I want the row which has 0-row result comes in output results, in summary, if I have 10 regions, 20 category and 100 days( in date table ) the results should be 10 * 20 * 100 rows.
my question is something like MySQL Group by - Get columns with zero count but grouping on multiple fields( columns).

i get wrong results from mysql join query

I have 2 tables, that i want to join, one is rooms and another is reservations.
Basically I want to search for rooms which are not reserved (not in reservation table) and to get the details of those rooms (which are not in reservation table) from room table.
Here are my tables structure:
CREATE TABLE `room` (
`roomID` int(11) NOT NULL AUTO_INCREMENT,
`hotelID` int(11) NOT NULL,
`roomtypeID` int(11) NOT NULL,
`roomNumber` int(11) NOT NULL,
`roomName` varchar(255) NOT NULL,
`roomName_en` varchar(255) NOT NULL,
`roomDescription` text,
`roomDescription_en` text,
`roomSorder` int(11) NOT NULL,
`roomVisible` tinyint(4) NOT NULL,
PRIMARY KEY (`roomID`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8;
CREATE TABLE `reservation` (
`reservationID` int(11) NOT NULL AUTO_INCREMENT,
`customerID` int(11) NOT NULL,
`hotelID` int(11) NOT NULL,
`reservationCreatedOn` datetime NOT NULL,
`reservationCreatedFromIp` varchar(255) CHARACTER SET greek NOT NULL,
`reservationNumberOfAdults` tinyint(4) NOT NULL,
`reservationNumberOfChildrens` tinyint(4) NOT NULL,
`reservationArrivalDate` date NOT NULL,
`reservationDepartureDate` date NOT NULL,
`reservationCustomerComment` text CHARACTER SET greek,
PRIMARY KEY (`reservationID`)
) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8;
CREATE TABLE `reservationroom` (
`reservationroomID` int(11) NOT NULL AUTO_INCREMENT,
`reservationID` int(11) NOT NULL,
`hotelID` int(11) NOT NULL,
`roomID` int(11) NOT NULL,
PRIMARY KEY (`reservationroomID`)
) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8;
Here is the query that I have right now, which gives me wrong results:
SELECT * FROM room r
LEFT JOIN reservation re
ON r.hotelID = re.hotelID
WHERE re.hotelID = 13
AND NOT
(re.reservationArrivalDate >= '2014-07-07' AND re.reservationDepartureDate <= '2014-07-13')
I also have created a fiddle, with the data from both tables included:
http://sqlfiddle.com/#!2/4bb9ea/1
Any help will be deeply appreciated
Regards, John
i agree that room number was missed,
but query template should looks like
SELECT
*
FROM
room r
LEFT JOIN reservation re
ON r.hotelID = re.hotelID
WHERE r.hotelID = 2
AND NOT (
re.hotelID IS NOT NULL
AND re.reservationArrivalDate >= '2014-07-07'
AND re.reservationDepartureDate <= '2014-09-23'
) ;
You need change table in where statement from reservation to room. Also you need add re.hotelID to where statement as well, because on where statement you need check that record is not null ans only after try to check dates
Given the newly-added reservationroom table, consider using a NOT EXISTS sub-query to find rooms without reservations:
SELECT
*
FROM
room r
WHERE NOT EXISTS
(SELECT
*
FROM
reservationroom rr
WHERE
rr.reservationroomID = r.roomID
)

my join returns 0 results

I have to following 3 tables: room, reservation and reservationroom
Their structure is as follows:
CREATE TABLE `room` (
`roomID` int(11) NOT NULL AUTO_INCREMENT,
`hotelID` int(11) NOT NULL,
`roomtypeID` int(11) NOT NULL,
`roomNumber` int(11) NOT NULL,
`roomName` varchar(255) NOT NULL,
`roomName_en` varchar(255) NOT NULL,
`roomDescription` text,
`roomDescription_en` text,
`roomSorder` int(11) NOT NULL,
`roomVisible` tinyint(4) NOT NULL,
PRIMARY KEY (`roomID`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8;
CREATE TABLE `reservation` (
`reservationID` int(11) NOT NULL AUTO_INCREMENT,
`customerID` int(11) NOT NULL,
`hotelID` int(11) NOT NULL,
`reservationCreatedOn` datetime NOT NULL,
`reservationCreatedFromIp` varchar(255) CHARACTER SET greek NOT NULL,
`reservationNumberOfAdults` tinyint(4) NOT NULL,
`reservationNumberOfChildrens` tinyint(4) NOT NULL,
`reservationArrivalDate` date NOT NULL,
`reservationDepartureDate` date NOT NULL,
`reservationCustomerComment` text CHARACTER SET greek,
PRIMARY KEY (`reservationID`)
) ENGINE=InnoDB AUTO_INCREMENT=46 DEFAULT CHARSET=utf8;
CREATE TABLE `reservationroom` (
`reservationroomID` int(11) NOT NULL AUTO_INCREMENT,
`reservationID` int(11) NOT NULL,
`hotelID` int(11) NOT NULL,
`roomID` int(11) NOT NULL,
PRIMARY KEY (`reservationroomID`)
) ENGINE=InnoDB AUTO_INCREMENT=46 DEFAULT CHARSET=utf8;
(please note that foreign keys have been removed from create statements for sake of simplicity)
What I am trying to do: I want to get all rooms that are not reserved for specific dates, that is only the free rooms from the specific hotel (I have its ID)
Here is the query that I have right now:
SELECT r.* FROM room r
LEFT JOIN `reservationroom` rr
ON r.`hotelID` = rr.`hotelID`
AND r.`roomID` = rr.`roomID`
LEFT JOIN `reservation` re
ON rr.`reservationID` = re.`reservationID`
WHERE (rr.`reservationroomID` = ''
OR rr.`reservationroomID` IS NULL
AND re.`reservationArrivalDate` >= 2014-08-27
AND re.`reservationDepartureDate` <= 2014-08-29
AND r.`hotelID` = 10
AND r.`roomVisible` = 1);
This query now returns 0 results. It should return 9 records, since the hotel with ID = 10 has 9 rooms that are free (no resevations for specific dates exist in the reservation table)
Can anyone give me a hand with this please? I am trying to sort this out couple of hours, without any success.
You are using left join, so conditions on all but the first table should be in the on clauses. I think you want a query more like this:
SELECT r.*
FROM room r LEFT JOIN
`reservationroom` rr
ON r.`hotelID` = rr.`hotelID` AND
r.`roomID` = rr.`roomID` LEFT JOIN
`reservation` re
ON rr.`reservationID` = re.`reservationID` AND
re.`reservationArrivalDate` >= 2014-08-27 AND
re.`reservationDepartureDate` <= 2014-08-29
WHERE r.`hotelID` = 10 AND r.`roomVisible` = 1 AND re.reservationID is null;
I'm not sure what the comparison is to the empty string. It doesn't seem necessary for this purpose.

how to create a team leaderboard with info from 4 tables?

This is tricky, I have been tasked with creating an team leader board where individuals complete tasks for a score. The score is defined in the table "station" and every time a user completes a task- a post is created in the posts table with the id of the station and their RFID (radio frequency ID). There is a team table which defines the team name.
i need a way to get the sum of all the post scores (joined points from stations table) a teams members have participated in.
The result should be sorted be team score and look something like if we have 4 teams with 4 members who participated in 4 events- whats the total score for each team
Team name one (Teams.name) | score
Team name two (Teams.name) | score
Team name three (Teams.name) | score
The tables -
CREATE TABLE `posts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`rfid` varchar(50) NOT NULL,
`station_id` int(11) NOT NULL,
`updated_at` datetime NOT NULL,
`created_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=11 ;
-- --------------------------------------------------------
Table structure for table stations
CREATE TABLE `stations` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`description` text NOT NULL,
`points` int(11) NOT NULL,
`logic` varchar(200) NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1023 ;
-- --------------------------------------------------------
Table structure for table teams
CREATE TABLE `teams` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;
-- --------------------------------------------------------
Table structure for table users
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`rfid` varchar(50) NOT NULL,
`first_name` varchar(50) NOT NULL,
`last_name` varchar(50) NOT NULL,
`team` int(11) NOT NULL,
`quiz_score` int(11) NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
I have created an query for an individual leaderboard-
SELECT users.first_name, users.last_name, posts.rfid, sum(stations.points) score
FROM posts
JOIN users ON posts.rfid = users.rfid
JOIN stations ON posts.station_id = stations.id
GROUP BY posts.rfid
ORDER BY score DESC LIMIT 0 , 100
this is what i have got so far for the team one
SELECT name, (SELECT sum(stations.points) score FROM posts
JOIN users ON posts.rfid = users.rfid
JOIN stations ON posts.station_id = stations.id
WHERE users.team = teams.id
GROUP BY posts.rfid) team_score FROM teams
//subquery returns more than one row
I think this might be the correct answer
SELECT name,
(SELECT sum(stations.points) score FROM posts
JOIN users ON posts.rfid = users.rfid
JOIN stations ON posts.station_id = stations.id
WHERE users.team = teams.id ) team_score
FROM teams

How can I select the current holder for each championship?

I want to select the current holders for each championship in a championships table, and return NULL for championships that have not had any winners yet.
Here are the create statements for the two tables:
CREATE TABLE `championships` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`friendly_name` varchar(255) NOT NULL,
`rank` int(2) unsigned NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`),
UNIQUE KEY `friendly_name` (`friendly_name`)
) ENGINE=InnoDB;
CREATE TABLE `title_history` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`championship` int(10) unsigned NOT NULL,
`winner` varchar(255) NOT NULL,
`date_from` date NOT NULL,
`location` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `championship` (`championship`)
) ENGINE=InnoDB;
ALTER TABLE `title_history` ADD CONSTRAINT `title_history_ibfk_1` FOREIGN KEY (`championship`) REFERENCES `championships` (`id`) ON UPDATE CASCADE;
What MySQL statement would return the data set I wanted?
Assuming you're storing the winner of a championship as the primary key/id of the holder, something like this should work. You might want to add in another join to get the actual name of the team from another table though.
Because LEFT join will only select rows from the 'right' table when there is a match, everything that doesn't have one should come back as NULL.
SELECT name, [holder]
FROM championships AS c
LEFT JOIN title_history AS h ON c.winner = h.id
EDITED VERSION:
With further insight into your tables and from your comment, maybe try this subselect:
SELECT friendly_name,
(SELECT winner FROM title_history WHERE championship = c.id ORDER BY date_from DESC LIMIT 1)
FROM championships AS c
ORDER BY name
If I understand your structure correctly, that ought to get the last winner of each championship?