How to perform IS_THE_SUBSET_OF function in MySQL? - mysql

Added: the CREATE code for student and takes
CREATE TABLE `student` (
`sid` VARCHAR(6) NOT NULL,
`sname` VARCHAR(6) NULL DEFAULT NULL,
`sex` VARCHAR(2) NULL DEFAULT NULL,
`age` TINYINT(3) UNSIGNED NULL DEFAULT NULL,
`dept` VARCHAR(50) NULL DEFAULT NULL,
`class` VARCHAR(4) NULL DEFAULT NULL,
PRIMARY KEY (`sid`)
);
CREATE TABLE `takes` (
`sid` VARCHAR(6) NOT NULL,
`cid` VARCHAR(3) NOT NULL,
`score` TINYINT(3) UNSIGNED NULL DEFAULT NULL,
PRIMARY KEY (`sid`, `cid`)
)
I am going to display the IDs and names of all students who have taken the courses which are taken by the student whose ID is '31401'. I have the following code:
SELECT sid, sname
FROM student S
WHERE NOT EXISTS((SELECT cid
FROM takes
WHERE sid = '31401')
EXCEPT
(SELECT cid
FROM takes T
WHERE S.sid = T.sid));
However, there is no EXCEPT operation in MySQL. So I wonder if I could rewrite like this:
SELECT sid, sname
FROM student S
WHERE ((SELECT cid
FROM takes
WHERE sid = '31401')
IS_THE_SUBSET_OF
(SELECT cid
FROM takes T
WHERE S.sid = T.sid));
How can I implement the IS_THE_SUBSET_OF function?

There is no set-based operator that does what you want. You can use join, group by and some other logic:
select t.sid
from takes t join
takes ts
on t.cid = ts.cid and ts.sid = 31401 -- don't use single quotes for a numeric constant
group by t.sid
having count(*) = (select count(*) from takes ts2 where ts2.sid = 31401);
This formulation assumes that takes does not have duplicate sid/cid pairs.

Related

I want two tables calculate

I want to add and calculate using data from 2 tables.
The results I want are as follows.
However, if I send a query as follows:
SELECT COUNT(IF(treatment_fees_check_division = 'test',
treatment_fees_check_division, NULL)) AS COUNT, SUM(CASE WHEN
treatment_fees_check_division = 'test' THEN treatment_fees_difference
END) + SUM(advenced_amount) AS if_treatment_fees_check_division,
SUM(advenced_amount) AS sum_init_amount FROM ( SELECT
treatment_fees_check_division, treatment_fees_difference,
advenced_amount FROM hospital_payment_data, advenced_payment WHERE
hospital_payment_data.id = advenced_payment.chart_num ) AS a
These results occur.
create table of hospital_payment_data and data
CREATE TABLE `hospital_payment_data` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`date` TIMESTAMP NOT NULL DEFAULT current_timestamp(),
`chart_num` INT(11) NOT NULL ,
`chart_name` VARCHAR(50) NOT NULL,
`visit` DATE NOT NULL,
`non_payment_sales` VARCHAR(50) NOT NULL,
`total_medical_bills` VARCHAR(50) NOT NULL,
`total_amount` VARCHAR(50) NOT NULL,
`amount_asked` VARCHAR(50) NOT NULL,
`medical_bills_payment` VARCHAR(50) NOT NULL,
`personal_liability_amount` VARCHAR(50) NOT NULL,
`non_payment` VARCHAR(50) NOT NULL,
`insurance_division` VARCHAR(50) NOT NULL,
`division` VARCHAR(50) NOT NULL,
`cash_amount_received` VARCHAR(50) NOT NULL,
`cash_receipt` VARCHAR(50) NOT NULL,
`cash_receipt_non_payment` VARCHAR(50) NOT NULL,
`cash_receipt_payment` VARCHAR(50) NOT NULL,
`card_amount_received` VARCHAR(50) NOT NULL,
`card_non_payment` VARCHAR(50) NOT NULL,
`card_payment` VARCHAR(50) NOT NULL,
`medical_bills_check` VARCHAR(50) NOT NULL,
`medical_bills_check_modify` VARCHAR(50) NOT NULL DEFAULT 'N',
`treatment_fees_difference` VARCHAR(50) NOT NULL,
`init_amount` VARCHAR(50) NOT NULL DEFAULT '0',
`treatment_fees_check_division` VARCHAR(50) NOT NULL DEFAULT '-',
`treatment_fees_check` VARCHAR(50) NOT NULL,
`treatment_fees_check_modify` VARCHAR(50) NOT NULL DEFAULT 'N',
`treatment_fees_check_memo` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`)
)
COLLATE='euckr_korean_ci'
ENGINE=InnoDB
AUTO_INCREMENT=18
;
create table of advenced_payment and data
CREATE TABLE `advenced_payment` (`id` INT(11) NOT NULL AUTO_INCREMENT,
`date` TIMESTAMP NULL DEFAULT NULL,
`chart_num` VARCHAR(50) NULL DEFAULT NULL,
`chart_name` VARCHAR(50) NULL DEFAULT NULL,
`advenced_amount` VARCHAR(50) NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `chart_num` (`chart_num`)) COLLATE='euckr_korean_ci' ENGINE=InnoDB AUTO_INCREMENT=2 ;
How do fix my query??
You have numerous issues with you query. This won't fix your problems, but I recommend writing it as:
SELECT SUM(hpd.treatment_fees_check_division = 'test') AS COUNT,
(SUM(CASE WHEN hpd.treatment_fees_check_division = 'test' THEN hpd.treatment_fees_difference END) +
SUM(advenced_amount)
) AS if_treatment_fees_check_division,
SUM(advenced_amount) AS sum_init_amount
FROM hospital_payment_data hpd JOIN
advanced_payment ap
ON hpd.id = ap.chart_num;
This simplifies and fixes some issues:
The JOIN uses proper, explicit, standard, readable syntax. Never use commas in the FROM clause.
The subquery is utterly unnecessary and probably adversely affects performance.
All tables have table aliases.
All column references are qualified.
The condition count is much simplified using sum(<boolean>).
I note that treatment_fees_difference is a string, yet you are using SUM(). That is really, really bad.
In any case, your problem, is that one of the tables has multiple rows. It is hard to know which one but my guess is advanced_payment. The solution is to preaggregate before the JOIN:
SELECT SUM(hpd.treatment_fees_check_division = 'test') AS COUNT,
(SUM(CASE WHEN hpd.treatment_fees_check_division = 'test' THEN hpd.treatment_fees_difference END) +
SUM(ap.sum_init_amount)
) AS if_treatment_fees_check_division,
SUM(ap.sum_init_amount) AS sum_init_amount
FROM hospital_payment_data hpd JOIN
(SELECT ap.chart_num, COUNT(*) as cnt, SUM(advenced_amount) as sum_init_amount
FROM advanced_payment ap
GROUP BY ap.chart_num
) ap
ON hpd.id = ap.chart_num;

MySQL returning all matches from a table and indicating if an id is on another table

How can I return, on a select, a field that indicates that an id was found?
My goal is to return all songs(song) from a specific source(source) checking if an user(user) has it or not (user_song).
The query I made almost works. If I remove 'hasSong' (which Im trying to indicate that an user has a song or not), I can see all songs.
If I keep 'hasSong', I see all songs repeating the song for each user.
QUERY:
SELECT DISTINCT(song.id) AS id_song, CONCAT(song.article, ' ', song.name) AS name
FROM `song`
LEFT JOIN `user_song` ON `song`.`id` = `user_song`.`id_song`
LEFT JOIN `user` ON `user`.`id` = `user_song`.`id_user`
JOIN `song_source` ON `song`.`id` = `song_source`.`id_song`
WHERE `song_source`.`id_source` = '1'
AND ( `user_song`.`id_user` = '3' OR song.id = song_source.id_song )
ORDER BY `song`.`name` ASC
DB:
CREATE TABLE `song` (
`id` int(11) NOT NULL,
`article` varchar(10) NOT NULL,
`name` varchar(150) NOT NULL,
`shortname` varchar(150) NOT NULL,
`year` int(11) NOT NULL,
`artist` int(11) NOT NULL,
`duration` int(11) NOT NULL,
`genre` int(11) NOT NULL,
`updated` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `song_source` (
`id_song` int(11) NOT NULL,
`id_source` int(11) NOT NULL
)
CREATE TABLE `source` (
`id` int(11) NOT NULL,
`article` varchar(10) NOT NULL,
`name` varchar(150) NOT NULL,
`updated` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `user` (
`id` int(11) NOT NULL,
`email` varchar(100) NOT NULL,
`password` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `user_song` (
`id_user` int(11) NOT NULL,
`id_song` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
The specification isn't entirely clear, ...
To return all songs (with no repeated values of song.id) that are from a particular source (id_source='1'),
along with an indicator, a value of 0 or 1, that tells us if there's a row in user_song that matches on id_song and is related to a particular user,(id_user = '3')
something like this:
SELECT s.id AS id_song
, MAX( CONCAT(s.article,' ',s.name) ) AS name
, MAX( IF(us.id_user = '3' ,1,0) ) AS has_song
FROM `song` s
JOIN `song_source` ss
ON ss.id_song = s.id
AND ss.id_source = '1'
LEFT
JOIN `user_song` us
ON us.id_song = s.id
AND us.id_user = '3'
GROUP BY s.id
ORDER BY MAX(s.name)
There are a couple of other query patterns that will return an equivalent result. For example, we could use a correlated subquery in the SELECT list.
SELECT s.id AS id_song
, MAX( CONCAT(s.article,' ',s.name) ) AS name
, ( SELECT IF( COUNT(us.id_user) >0,1,0)
FROM `user_song` us
WHERE us.id_song = s.id
AND us.id_user = '3'
) AS has_song
FROM `song` s
JOIN `song_source` ss
ON ss.id_song = s.id
AND ss.id_source = '1'
GROUP BY s.id
ORDER BY MAX(s.name)
These queries are complicated by the fact that there are no guarantees of uniqueness in any of the tables. If we had guarantees, we could eliminate the need for a GROUP BY and aggregate functions.
Please consider adding PRIMARY and/or UNIQUE KEY constraints on the tables, to prevent duplication. The way the tables are defined, we could add multiple rows to song with the same id value. (And those could have different name values.)
(And the queries would be much simpler if we had some guarantees of uniqueness.)

MySql Join that returns none existing records with nulls

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.

View help. Pulling data from 3 tables

Okay, I need some major help with this subject. This is what I need the view to do. It needs to take Sum of the DKP_Change Column in the Attendance table
SELECT SUM(a.DKP_Change) FROM Attendance AS a GROUP BY Name
add the value of the initial DKP from the characters table
SELECT b.Inital_DKP FROM Characters AS b GROUP BY Name
Subtract the sum of the raid drops tabe cost
SELECT SUM(c.Cost) FROM Raid_Drops AS c GROUP BY Name
I'm entirely new to the idea of VIEWS and i'm not sure where to begin with, the name of the view should be DKP, the columns should be Name and Total_DKP, where total dkp is calculated from teh above select statements.
Here are the creates for all 3 tables.
CREATE TABLE `Attendance` (
`Date` date NOT NULL,
`Name` varchar(20) NOT NULL,
`Hours` int(11) NOT NULL,
`Penalty` float NOT NULL,
`Rank` set('Raider','Core','Elite') NOT NULL,
`Rate` int(11) NOT NULL,
`DKP_Change` float NOT NULL,
`RecordNumber` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`RecordNumber`)
) ENGINE=MyISAM AUTO_INCREMENT=15 DEFAULT CHARSET=latin1
CREATE TABLE `Characters` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Name` varchar(25) NOT NULL,
`Class` varchar(25) NOT NULL,
`Spec` varchar(25) NOT NULL,
`Position` set('Healer','Tank','DPS') NOT NULL COMMENT 'Healer, Tank, or DPS',
`Usable` set('Cloth','Mail','Plate') NOT NULL COMMENT 'Type of Usable Armor? Cloth, Mail, Or Plate',
`Primary Stat` set('Agility','Strength','Intellect','Healer','Tank') NOT NULL COMMENT 'Used for Sorting Only(ie dps trinket with agility strength dps not eligible)',
`Initial_DKP` int(11) NOT NULL COMMENT 'DKP given at the start of current tier.',
`Total_DKP` int(11) NOT NULL COMMENT 'Huge Complicated Mess.',
PRIMARY KEY (`ID`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1
CREATE TABLE `Raid_Drops` (
`Record Number` int(11) NOT NULL,
`Date` date NOT NULL,
`Name of Item` varchar(25) NOT NULL,
`Item Slot` enum('Main Hand','Off Hand','Head','Neck','Shoulder','Back','Chest','Wrist','Hands','Waist','Legs','Feet','Ring 1','Ring 2','Trinket 1','Trinket 2') NOT NULL,
`Player_Name` varchar(25) NOT NULL,
`Cost` float NOT NULL,
PRIMARY KEY (`Record Number`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
You could
Join the three tables in a subselect, grouping on Name
Perform your calculations on the results of each subselect
The only part that's not entirely clear to me is if the names in Characters are unique or not. If they are, you can drop the group by. If they are not, the AVG might give you unexpected results.
SQL Statement
SELECT sumA
, initialB
, sumC
, sumA + initialB - sumC
, a.Name
FROM (
SELECT Name, SUM(DKP_Change) AS sumA
FROM Attendance
GROUP BY Name
) AS a
INNER JOIN (
SELECT Name, Inital_DKP AS initialB
FROM Characters
) AS b ON a.Name = b.Name
INNER JOIN (
SELECT Name, SUM(Cost) AS sumC
FROM Raid_Drops
GROUP BY Name
) AS c ON c.Name = b.Name

Complex mySQL Query (again)

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.