Join Two tables multiple times - mysql

I need result from two tables , where one is parent table and other is child table as well as parent table it self for sub level child entries.
if i do the sql query like:
SELECT cc.collection_id, cc.title, cc.type, cc.alias as forum_alias,
SUBSTRING(cc.description,1,200) as short_desc,
COUNT(b1.boardmessage_id) as total_threads,
COUNT(b2.boardmessage_id) as total_replies
FROM contentcollections cc
JOIN boardmessages b1 ON b1.parent_id = cc.collection_id
JOIN boardmessages b2 ON b2.collection_id = cc.collection_id
WHERE cc.type=1
AND cc.is_active=1
AND b1.parent_type='collection'
AND b1.is_active=1
AND b2.parent_type IN('message','reply','reply_on_reply')
GROUP BY cc.collection_id
ORDER BY cc.created DESC;
it gives me the wrong out put with same number of total threads and same number of total replies.How ever if i do something like this
SELECT cc.collection_id, cc.title,cc.type, cc.alias as forum_alias,
SUBSTRING(cc.description,1,200) as short_desc,
(SELECT COUNT(boardmessage_id)
FROM boardmessages
WHERE parent_type='collection'
AND collection_id=cc.collection_id
AND is_active=1) as total_threads,
(SELECT count(boardmessage_id)
FROM boardmessages
WHERE parent_type IN('message','reply','reply_on_reply')
AND collection_id=cc.collection_id AND is_active=1) as total_replies
FROM contentcollections cc
WHERE cc.type=? AND cc.is_active=?
ORDER BY cc.created DESC
It gives me the correct answer.
I suspect i am using sub queries in the second option so it may slow down the performance of the page rendering.
Please suggest me for the same.Any help or suggestion would be greatly appreciated.
Thanks

Replace:
COUNT(b1.boardmessage_id) as total_threads,
COUNT(b2.boardmessage_id) as total_replies
With:
COUNT(DISTINCT b1.boardmessage_id) as total_threads,
COUNT(DISTINCT b2.boardmessage_id) as total_replies
if you only want each row to count once, instead of the default, counting all combinations.
If you have 3 rows in b1 and 5 rows in b2, you get a total of 15 rows, and both counts return that there are 15 rows, with the distinct flag you get the answers 3 and 5 instead, as its 3 distinct values in b1, and 5 distinct values in b2.

Related

need to query 2 MySQL tables with COUNT(*) condition

I have 2 tables (cycles and merged_cycles). "cycles" has 2 fields I need to target (userid and cycleid) and "merged_cycles" also has 2 targeted fields (cycleid1 and cycleid2). I need to know all cycles.userid that have more than one record in "cycles", so long as the corresponding cycles.cycleid for any matching record does not appear in any record in "merged_cycles" in either merged-cycles.cycleid1 OR merged_cycles.cycleid2. I currently have it working using 2 different queries, but i was curious if it could be done in one. Here's what i have tried so far:
SELECT cycles.cycleid, cycles.userid, cycles.COUNT(*),
merged_cycles.cycleid1, merged_cycles.cycleid2
FROM cycles,merged_cycles
WHERE merged_cycles.cycleid1 != cycles.cycleid && merged_cycles.cycleid2 != cycles.cycleid
GROUP BY cycles.userid
HAVING cycles.count(*) > 1
Thanks for any suggestions!
I think this does what you want:
SELECT c.cycleid
FROM cycles c
WHERE NOT EXISTS (SELECT 1
FROM merged_cycles mc
WHERE c.cycleid IN (mc.cycleid1, mc.cycleid2)
)
GROUP BY c.userid
HAVING count(*) > 1;

MySQL MAX from count query

I have table rozpis_riesitelov which contains columns :
id_rozpisu_riesit, id_zam, id_projektu, id_ulohy.
I made query :
select id_zam, id_ulohy, count(*) as counted
from rozpis_riesitelov
group by id_zam
having id_ulohy in (1,2,8)
which shows me id of employee (id_zam) and how many times He was in project (id_ulohy is irrevelant but I had to select it beacuse of having clause). It shows me everyone in db but I am looking for employee with ID of 4 who is in 6 projects (Yes, I could do order by but I want to see max). When I do max of this query like this:
select max(counted)
from (select id_zam, id_ulohy, count(id_zam) as counted
from rozpis_riesitelov
group by id_zam
having id_ulohy in (1,2,8)) as riesitel
which shows me number 149 instead of 6.
So basically I only need to find employee that occurs in the most of the projects.
What's wrong with sorting by the COUNT() value, and limiting to one result?
SELECT `id_zam`,
`id_ulohy`,
COUNT(*) AS `counted`
FROM `rozpis_riesitelov `
WHERE `id_ulohy` IN ( 1, 2, 8 )
GROUP BY `id_zam`
ORDER BY `counted` DESC
LIMIT 1
Not sure exactly what you are trying to accomplish but you only use HAVING to filter on your aggregate like this:
HAVING COUNT(*) > 1
you should be able to move the condition to a WHERE clause and get correct max returned:
select max(counted)
from (select id_zam, count(id_zam) as counted
from rozpis_riesitelov
where id_ulohy in (1,2,8)
group by id_zam) as riesitel

Sql query to sum up total of columns previously used aggregate function

From this post, enter link description here
I would like to improve the query
SELECT `BetType`,
count(`BetType`) AS COUNT,
sum(`BetAmount`) AS BetAmountTotal,
sum(`Payout`) AS PayoutTotal
FROM `betdb`
LEFT JOIN `matchdb` ON `betdb`.`MatchID` = `matchdb`.`MatchID`
WHERE `betdb`.`MatchID`=135
GROUP BY `BetType`
thanks to Sadikhasan, who helped on this query
I would like to add another row showing the totals of the columns
BetType Count BetAmount Total Payout Total
Handi 2 60000 950000
Homerun Count 4 10000 0
Total 6 70000 950000
this seems to be needing another SELECT statement but how would I put another row explicitly showing the "Total" string and getting the sum of the previously used columns with Aggregate Functions?
You can use WITH ROLLUP modifier to GROUP BY, which will give you another row with totals, but the column you group on (BetType) will show NULL for that row. But nothing stops you from using COALESCE() to replace that NULL with 'Total' string.
SELECT COALESCE(`BetType`,'Total') AS BetType,
COUNT(*) AS `Count`,
sum(BetAmount) AS BetAmountTotal,
sum(Payout) AS PayoutTotal
FROM betdb
WHERE betdb.MatchID=135
GROUP BY BetType WITH ROLLUP

how to search for a given sequence of rows within a table in SQL Server 2008

The problem:
We have a number of entries within a table but we are only interested in the ones that appear in a given sequence. For example we are looking for three specific "GFTitle" entries ('Pearson Grafton','Woolworths (P and O)','QRX - Brisbane'), however they have to appear in a particular order to be considered a valid route. (See image below)
RowNum GFTitle
------------------------------
1 Pearson Grafton
2 Woolworths (P and O)
3 QRX - Brisbane
4 Pearson Grafton
5 Woolworths (P and O)
6 Pearson Grafton
7 QRX - Brisbane
8 Pearson Grafton
9 Pearson Grafton
So rows (1,2,3) satisfy this rule but rows (4,5,6) don't even though the first two entries (4,5) do.
I am sure there is a way to do this via CTE's but some help would be great.
Cheers
This is very simple using even good old tools :-) Try this quick-and-dirty solution, assuming your table name is GFTitles and RowNumber values are sequential:
SELECT a.[RowNum]
,a.[GFTitle]
,b.[GFTitle]
,c.[GFTitle]
FROM [dbo].[GFTitles] as a
join [dbo].[GFTitles] as b on b.RowNumber = a.RowNumber + 1
join [dbo].[GFTitles] as c on c.RowNumber = a.RowNumber + 2
WHERE a.[GFTitle] = 'Pearson Grafton' and
b.[GFTitle] = 'Woolworths (P and O)' and
c.[GFTitle] = 'QRX - Brisbane'
Assuming RowNum has neither duplicates nor gaps, you could try the following method.
Assign row numbers to the sought sequence's items and join the row set to your table on GFTitle.
For every match, calculate the difference between your table's row number and that of the sequence. If there's a matching sequence in your table, the corresponding rows' RowNum differences will be identical.
Count the rows per difference and return only those where the count matches the number of sequence items.
Here's a query that implements the above logic:
WITH SoughtSequence AS (
SELECT *
FROM (
VALUES
(1, 'Pearson Grafton'),
(2, 'Woolworths (P and O)'),
(3, 'QRX - Brisbane')
) x (RowNum, GFTitle)
)
, joined AS (
SELECT
t.*,
SequenceLength = COUNT(*) OVER (PARTITION BY t.RowNum - ss.RowNum)
FROM atable t
INNER JOIN SoughtSequence ss
ON t.GFTitle = ss.GFTitle
)
SELECT
RowNum,
GFTitle
FROM joined
WHERE SequenceLength = (SELECT COUNT(*) FROM SoughtSequence)
;
You can try it at SQL Fiddle too.

MS Access Crosstab query - sum of columns reported by month

I am putting together a Crosstab and I want a report for multiple column values (all numbers) grouped by month. Here is the SQL I used. I understand that this won't bring back the desired results. every "timex" column has a different number in it. I want a query that will return the sum of the column grouped by month.
TRANSFORM Sum(tblTimeTracking.time1+ tblTimeTracking.time2+ tblTimeTracking.time3+ tblTimeTracking.time4+ tblTimeTracking.time5+ tblTimeTracking.time6+ tblTimeTracking.time7+ tblTimeTracking.time8+ tblTimeTracking.time9+ tblTimeTracking.time10+ tblTimeTracking.time11+ tblTimeTracking.time12+ tblTimeTracking.time13+ tblTimeTracking.time14+ tblTimeTracking.time15+ tblTimeTracking.time16+ tblTimeTracking.time17+ tblTimeTracking.time18+ tblTimeTracking.time19+ tblTimeTracking.time20+ tblTimeTracking.time21+ tblTimeTracking.time22 ) AS Total
SELECT tbl_vlookup.Manager AS Manager
FROM tbl_vlookup INNER JOIN tblTimeTracking ON tbl_vlookup.[Associate Name] = tblTimeTracking.Associate
GROUP BY tbl_vlookup.Manager
PIVOT Format([Day],"yyyy-mm");
Associate Day Time 1 Time 2 Time 3 Time 4 Time 5 Time 6 Time 7
John Smith 12/1/9999 1 0 0 5.5 1 0.25 0.25
Something like this:
TRANSFORM Sum(q.Time1) AS SumOfTime1
SELECT q.Associate, q.Day
FROM (SELECT t.Associate, t.Day, t.Time1,"Time1" As TimeType
FROM tbl t
UNION ALL
SELECT t.Associate, t.Day, t.Time2,"Time2" As TimeType
FROM tbl t
UNION ALL
SELECT t.Associate, t.Day, t.Time3,"Time3" As TimeType
FROM tbl t) AS q
GROUP BY q.Associate, q.Day
PIVOT q.TimeType;
As I mentioned, you need to flatten the table. It only seems to be different types of data :)