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
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
)
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.
I have a query i am working on and i am taking the max records for each socialSecurityNumber from a table tblmovementhyst. This works fine however i would like to join back to the citizen table to display also records that are in the tblcitizens table but does not exist in the tblmovementhyst.
The primary key for the tblcitizens is socialSecurityNumber and the primary key for tblmovementhyst is citizenPositionNo. Under is he code of what i have thus far:
SQL
select m.citizenSocialSecurityNumber,CONCAT(c.fName,' ',c.lName)as name,
CONCAT(m.latAdd,',',m.longAdd)as latlng, t.citizenTypeId,max(m.citizenPositionNo)as positionNo
from tblcitizens c LEFT JOIN tblcitizenType t
ON c.citizenTypeId = t.citizenTypeId
LEFT JOIN tblmovementhyst m
ON m.citizenSocialSecurityNumber = c.socialSecurityNumber;
tblmovementhyst
TABLE `tblmovementhyst` (
`citizenPositionNo` int(11) NOT NULL AUTO_INCREMENT,
`citizenSocialSecurityNumber` int(11) NOT NULL,
`latAdd` decimal(18,14) NOT NULL,
`longAdd` decimal(18,14) NOT NULL,
`date` varchar(10) NOT NULL,
`time` time NOT NULL,
PRIMARY KEY (`citizenPositionNo`)
tblcitizens
TABLE `tblcitizens` (
`socialSecurityNumber` int(11) NOT NULL,
`fName` varchar(30) NOT NULL,
`lName` varchar(30) NOT NULL,
`oName` varchar(30) DEFAULT NULL,
`citizenTypeId` int(11) NOT NULL,
`dob` date NOT NULL,
PRIMARY KEY (`socialSecurityNumber`)
You should use a LEFT JOIN, that returns all rows from the first table and only the rows that matches on the second one:
SELECT ..., MAX(m.citizenPositionNo) AS positionNo
FROM
tblcitizens c LEFT JOIN tblcitizenType t
ON c.citizenTypeId = t.citizenTypeId
LEFT JOIN tblmovementhyst m
ON m.citizenSocialSecurityNumber = c.socialSecurityNumber
GROUP BY
...
In case that there is a record on tblcitizens but not on tblmovementhyst, MAX(citizenPositionNo) will be NULL.
My apologies that the question title is not more specific.
I am working on a system that involves stock control and membership records. The current problem relates to the 'membership packs' that are given to new members on joining; there are a variety of membership types and each one gets a pack with several items in, no two packs are exactly the same but there is some overlap with some products being used in more than one pack. I need to calculate the number of each product that is used in a given batch of new members.
I can create a query that gives me the total of different membership types in a batch.
I can create a query that give me the total of each product required to make one of each of those packs.
I need to create a query that is a combination of both.
The query that gives the total of each type in a batch:
SELECT COUNT(*) AS theCount, membershipPackType
FROM inputBatches
LEFT JOIN inputActions ON inputActionID = inputBatchAction
LEFT JOIN members ON memberID = inputBatchMemberID
LEFT JOIN membershipPacks ON membershipPackType = memberMembershipType
LEFT JOIN memPack ON memPackInputBatch = inputBatchID
WHERE memPackBookedOut = 'U'
AND inputActionAbbr <> 'E'
GROUP BY membershipPackType
ORDER BY membershipPackType;
This query produces the output at the top of the linked image:
The query that gives the total of each product to make one of each of the types from the result of the above query:
SELECT COUNT(*) AS theCount, stockItem
FROM membershipPackItems
LEFT JOIN membershipPacks ON membershipPackNumber = membershipPackType
LEFT JOIN stock ON stockNumber = membershipPackItemNo
WHERE membershipPackNumber = 11 OR membershipPackNumber = 12 OR membershipPackNumber = 13 OR membershipPackNumber = 14 OR membershipPackNumber = 23 OR membershipPackNumber = 24 OR membershipPackNumber = 25
GROUP BY stockItem
ORDER BY stockNumber;
This query produces the output at the bottom of this image:
http://www.kidderminsterharriers.com/images/query4.png
If I could combine the two queries then I wouldn't have the WHERE clause in the second query that is hard-coded like that. Also, what this second query doesn't allow for is that the membershipPackItems table includes a field for quantity; it assumes that the quantity of each item per pack is 1.
The ultimate aim is to have query that outputs in a similar fashion to the second query but that the column that is currently 'theCount' is a total allows for the number of each item in the pack (ie more than 1 if needed) and then multiplied up by the number of packs in the batch; in this case those items that currently have a count of 7 (there's 7 different types in this batch and those items appear in all of them) would be 62 (there's 62 members total in this batch).
This is the structure of the data tables used:
CREATE TABLE membershipPackItems (
membershipPackItemID int(10) NOT NULL auto_increment,
membershipPackNumber int(7) NOT NULL,
membershipPackItemNo varchar(6) NOT NULL,
membershipPackItemQty int(7) NOT NULL,
PRIMARY KEY (membershipPackItemID)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=71 ;
CREATE TABLE membershipPacks (
membershipPackID int(5) NOT NULL auto_increment,
membershipPackTitle varchar(50) default NULL,
membershipPackType int(5) default NULL,
PRIMARY KEY (membershipPackID)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=13 ;
CREATE TABLE stock (
stockID int(10) NOT NULL auto_increment,
stockNumber int(8) NOT NULL,
stockItem varchar(50) NOT NULL,
stockNominalNo int(14) NOT NULL,
stockVATNo int(3) NOT NULL,
stockDecLevel varchar(1) NOT NULL,
stockPeriodSold int(14) NOT NULL,
stockPeriodSoldValue float NOT NULL,
stockPPurchased int(14) NOT NULL,
stockYTDSold int(14) NOT NULL,
stockYTDSoldValue float NOT NULL,
stockYTDPurchased int(14) NOT NULL,
stockDefectLevel int(14) NOT NULL,
stockCurrentLevel int(14) NOT NULL,
stockReOrderLevel int(14) NOT NULL,
stockHolding int(14) NOT NULL,
stockBackOrderQty int(14) NOT NULL,
stockRetail float NOT NULL,
stockCost float NOT NULL,
stockOrdered int(14) NOT NULL,
stockSupplierNo int(7) NOT NULL,
stockSupplierStockNo varchar(20) NOT NULL,
stockDeliveryDate date NOT NULL,
stockDeleted varchar(1) NOT NULL,
stockAllowedLeaps varchar(1) NOT NULL,
stockCount int(14) NOT NULL,
stockCountDate date NOT NULL,
stockCountComment varchar(30) NOT NULL,
stockGroup1 varchar(4) NOT NULL,
stockGroup2 varchar(4) NOT NULL,
stockNewStockNo varchar(6) NOT NULL,
stockStatus int(3) NOT NULL,
PRIMARY KEY (stockID)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1779 ;
CREATE TABLE inputBatches (
inputBatchID int(10) NOT NULL auto_increment,
inputBatchInputNumber int(8) NOT NULL,
inputBatchMemberID int(8) NOT NULL,
inputBatchAction int(5) NOT NULL,
inputBatchDate date NOT NULL,
PRIMARY KEY (inputBatchID)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=88 ;
CREATE TABLE members (
memberID int(6) NOT NULL auto_increment,
memberCentre int(5) NOT NULL,
memberMembershipNo int(15) NOT NULL,
memberSurname varchar(50) NOT NULL,
memberForename varchar(50) NOT NULL,
memberSecondName varchar(50) NOT NULL,
memberParentTitle int(3) NOT NULL,
memberParentSurname varchar(50) NOT NULL,
memberParentForename varchar(50) NOT NULL,
memberStreet1 varchar(100) NOT NULL,
memberStreet2 varchar(100) NOT NULL,
memberTown varchar(50) NOT NULL,
memberCounty varchar(20) NOT NULL,
memberPostcode varchar(10) NOT NULL,
memberPhoneSTD varchar(6) NOT NULL,
memberPhone varchar(20) NOT NULL,
memberMobile varchar(20) NOT NULL,
memberEmail varchar(255) NOT NULL,
memberDOB date NOT NULL,
memberJoined date NOT NULL,
memberGender enum('m','f') NOT NULL,
memberSibling enum('no','yes') NOT NULL default 'no',
memberMembershipType int(3) NOT NULL,
memberSpecNeedsNo int(5) NOT NULL,
memberPromoNo int(5) NOT NULL,
memberDataProtect enum('no','yes') NOT NULL default 'no',
memberReceived date NOT NULL,
memberMemberType int(4) NOT NULL,
memberSendPack enum('no','yes') NOT NULL default 'no',
memberSendGift enum('no','yes') NOT NULL default 'no',
memberExpire date NOT NULL,
memberDespatched date NOT NULL,
memberInputNo int(10) NOT NULL,
memberSSC int(10) NOT NULL,
memberPrevStreet1 varchar(100) NOT NULL,
memberPrevStreet2 varchar(100) NOT NULL,
memberPrevTown varchar(50) NOT NULL,
memberPrevCounty varchar(20) NOT NULL,
memberPrevPostcode varchar(10) NOT NULL,
memberPrevCentre varchar(5) NOT NULL,
memberInvoiced float NOT NULL,
memberPaid float NOT NULL,
memberSpecNeedsString varchar(255) NOT NULL,
memberNotes mediumtext,
memberMembershipYear int(3) default '1',
PRIMARY KEY (memberID),
UNIQUE KEY memberMembershipNo (memberMembershipNo),
KEY memberFullName (memberSurname,memberForename),
KEY memberSurname (memberSurname),
KEY memberForename (memberForename)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=631747 ;
CREATE TABLE memPack (
memPackID int(10) NOT NULL auto_increment,
memPackBookedOut varchar(1) NOT NULL,
memPackDate date NOT NULL,
memPackMembershipNo int(14) NOT NULL,
memPackLicenseeNo int(7) NOT NULL,
memPackMemTypeNo int(7) NOT NULL,
memPackInputNumber int(13) NOT NULL,
memPackInputBatch int(10) NOT NULL,
memPackCentreNo int(14) NOT NULL,
PRIMARY KEY (memPackID)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=13675 ;
You can combine both queries by joining them on membershipPackType.
The INNER JOIN with your first query takes care of the hardcoded WHERE clause.
SQL Statement
SELECT COUNT(*) AS theCount
, stockItem
FROM membershipPackItems
LEFT JOIN membershipPacks ON membershipPackNumber = membershipPackType
LEFT JOIN stock ON stockNumber = membershipPackItemNo
INNER JOIN (
SELECT COUNT(*) AS theCount
, membershipPackType
FROM inputBatches
LEFT JOIN inputActions ON inputActionID = inputBatchAction
LEFT JOIN members ON memberID = inputBatchMemberID
LEFT JOIN membershipPacks ON membershipPackType = memberMembershipType
LEFT JOIN memPack ON memPackInputBatch = inputBatchID
WHERE memPackBookedOut = 'U'
AND inputActionAbbr <> 'E'
GROUP BY
membershipPackType
) cnt ON cnt.membershipPackType = membershipPackItems.membershipPackType
GROUP BY stockItem
ORDER BY stockNumber;
Edit
I have trimmed down the scripts and altered your first query as below in an effort to try and understand what is what.
If you provide some scripts to fill the tables with some data (preferably the data that should become the outputs you've posted), I am willing to have another look at it, otherwise, this is as far as I am prepared to go with this, sorry.
Note: that you should definitly strive for a consistent naming scheme. membershipPackItemNo in one table is stockNumber in an other, Packtype links with PackNumber, memPackInputBatch links with inputBatchID. If not for your own sanity, it would make it much easier for us to figure out what is what.
Note: the scripts have been changed for SQL Server. I don't have a MySQL running.
CREATE TABLE membershipPackItems (
membershipPackNumber INTEGER NOT NULL,
membershipPackItemNo varchar(6) NOT NULL,
)
CREATE TABLE membershipPacks (
membershipPackType INTEGER default NULL,
)
CREATE TABLE stock (
stockNumber INTEGER NOT NULL,
stockItem varchar(50) NOT NULL,
)
CREATE TABLE inputBatches (
inputBatchID INTEGER NOT NULL IDENTITY(1, 1),
inputBatchMemberID INTEGER NOT NULL,
inputBatchAction INTEGER NOT NULL,
)
CREATE TABLE members (
memberID INTEGER NOT NULL IDENTITY(1, 1),
memberMembershipType INTEGER NOT NULL,
)
CREATE TABLE memPack (
memPackBookedOut varchar(1) NOT NULL,
memPackInputBatch INTEGER NOT NULL,
)
SELECT COUNT(*) AS theCount, st.stockItem
FROM stock st
LEFT OUTER JOIN membershipPackItems mpi ON mpi.membershipPackItemNo = st.stockNumber
LEFT OUTER JOIN membershipPacks mp ON mp.membershipPackType = mpi.membershipPackNumber
WHERE mpi.membershipPackNumber = 11
GROUP BY stockItem
LOL PSEUDOCODE
Get the StockItem, and its quantity associated for each
membershipPackType. The ff is just a pseudocode but I am thinking that
you can create the actual SQL query to get what I am trying to get at.
MembershipPackType_Stock = SELECT membershipPackType,
StockItem, MembershipPackItemQty
FROM MembershipPackItems
LEFT JOIN MembershipPacks ON ...
LEFT JOIN stock ON ...
Get the number of members for each MembershipPackType in a Batch. The ff SQL query is directly taken from your post.
MembershipPackType_Count = SELECT COUNT(*) AS MemberCount, membershipPackType
FROM inputBatches
LEFT JOIN inputActions ON inputActionID = inputBatchAction
LEFT JOIN members ON memberID = inputBatchMemberID
LEFT JOIN membershipPacks ON membershipPackType = memberMembershipType
LEFT JOIN memPack ON memPackInputBatch = inputBatchID
WHERE memPackBookedOut = 'U'
AND inputActionAbbr <> 'E'
GROUP BY membershipPackType
ORDER BY membershipPackType;
3 Then you can easily join MembershipPackType_Stock and MembershipPackType_Count to get the total number for each StockItem. Once again, the ff is just a pseudocode but I hope that you'll get the idea.
SELECT StockItem, SUM( MemberCount * MembershipPackItemQty)
FROM MembershipPackType_Stock JOIN MembershipPackType_Count
ON MembershipPackType = ...
GROUP BY StockItem
I am not sure if this is what you are asking, but if I understand your question correctly, I think this is it.