How to count rows in table with condition WHERE? - mysql

There is a query that to count rows from table question_category:
SELECT
idSpecialization,
thematicspecialization.SpecializationName AS SpecializationName,
SubscrubeToUsersIdNote,
COUNT(question_categoryId) AS CNT,
COUNT(idSubscrubeToUsers) AS SUBS
FROM thematicspecialization
LEFT JOIN question_category ON question_category.question_categoryIdCategory = thematicspecialization.idSpecialization
LEFT JOIN question a ON a.idQuestion = question_category.question_categoryIdQuestion
LEFT JOIN subscrubetousers ON (subscrubetousers.SubscrubeToUsersIdNote = idSpecialization AND subscrubetousers.SubscrubeToUsersType = 4 AND SubscrubeToUsersStatus = 1)
WHERE a.country = 1
GROUP BY idSpecialization
Need display the category names of thematicspecialization with the condition WHERE a.country = 1 for joining tables question a ON a.idQuestion = question_category.question_categoryIdQuestion
In my case - the categories are not displayed.

This is too long for a ocmment.
This is your query, fixed up a bit to use table aliases so it is easier to read:
SELECT ts.idSpecialization, ts.SpecializationName, sts.SubscrubeToUsersIdNote,
COUNT(question_categoryId) AS CNT,
COUNT(idSubscrubeToUsers) AS SUBS
FROM thematicspecialization ts LEFT JOIn
question_category qc
ON qc.question_categoryIdCategory = ts.idSpecialization LEFT JOIN
question q
ON q.idQuestion = qc.question_categoryIdQuestion LEFT JOIN
subscrubetousers sts
ON (sts.SubscrubeToUsersIdNote = ts.idSpecialization AND
sts.SubscrubeToUsersType = 4 AND
sts.SubscrubeToUsersStatus = 1)
WHERE q.country = 1
GROUP BY idSpecialization;
Here are things that I notice:
The join between ts and qc is on IdCategory and idSpecialization. That seems like a strange combination of names.
The join between sts and ts is partly on SubscrubeToUsersIdNote and idSpecialization. That seems like a strange combination of names.
The where condition is turning some left joins into inner joins -- calling into question why you want left join anyway.
The two count columns are going to return very similar numbers, because they are counting non-NULL values on join keys`.
Your question is about "categories" and their "names". However, based on your query, it is entirely unclear what fields these refer to.
Based on this query, I have no idea what you are really trying to do. You should probably write another question, with sample data and desired output to express what you are trying to do. This question already has two answers. Clarifying it so it would be understood would (probably) invalidate the answers, which is impolite.

Not clear.
But I guess. You have a join with condition like
subscrubetousers.SubscrubeToUsersIdNote = idSpecialization AND subscrubetousers.SubscrubeToUsersType = 4 AND SubscrubeToUsersStatus = 1be this
May be this condition conflict thematicspecialization field

Related

mysql database problem in fetching data from 4 tables?

tbl_users
tbl_questions
tbl_answares
tbl_questions_votes
SELECT
`tbl_users`.`email`,
`tbl_questions`.`q_id`,
`tbl_questions`.`question`,
`tbl_questions`.`tags`,
`tbl_questions`.`posted_at`,
SUM(tbl_questions_votes.upvote) AS upvotes,
SUM(tbl_questions_votes.downvote) AS downvotes
FROM
`tbl_users`
INNER JOIN
`tbl_answares`
ON
`tbl_answares`.`user_id` = `tbl_users`.`user_id`
LEFT JOIN
`tbl_questions`
ON
`tbl_questions`.`q_id` = `tbl_answares`.`q_id`
LEFT JOIN
`tbl_questions_votes`
ON
`tbl_questions`.`q_id` = `tbl_questions_votes`.`q_id`
WHERE
`tbl_users`.`user_status` = 1 AND `tbl_answares`.`user_id` = '6'
GROUP BY
`tbl_questions`.`q_id`
ORDER BY
`tbl_questions`.`posted_at`
DESC
Above query is returning email of user that answered the question (another columns are right output) but, i want the email of the user that asked the question.
output: output
Expected Output
`tbl_users`.`email`, // email of user that asked the question
`tbl_questions`.`q_id`,
`tbl_questions`.`question`,
`tbl_questions`.`tags`,
`tbl_questions`.`posted_at`,
SUM(tbl_questions_votes.upvote) AS upvotes,
SUM(tbl_questions_votes.downvote) AS downvotes
Try changing the INNER JOIN on tbl_questions_votes to a LEFT JOIN, since I'd assume it doesn't matter if a question has votes or not.
Secondly, you're joining the table answares and questions both on user_id. I don't think this makes too much sense, it seems to me that you're fetching users with the questions that they did and all the answares they submmited; while the expected output is the questions that this user has answared!
So, I think it would make more sense if you joined like this:
INNER JOIN
tbl_answares
ON
tbl_answares.user_id = tbl_users.user_id
INNER JOIN
tbl_questions
ON
tbl_questions.q_id = tbl_answares.q_id
LEFT JOIN
tbl_questions_votes
ON
tbl_questions.q_id = tbl_questions_votes.q_id
LEFT JOIN
tbl_users usrs2
ON
tbl_questions.user_id = usrs2.user_id
This joins a user with his answares along with the answares particular questions and the votes casted for those questions, without excluding questions that has no votes; and finnally joining with the users that made each question you are retrieving.
If you have any doubts around joining tables in SQL, I recommend this great SO topic and this other one

MySQL Query limiting results by sub table

I'm really struggling with this query and I hope somebody can help.
I am querying across multiple tables to get the dataset that I require. The following query is an anonymised version:
SELECT main_table.id,
sub_table_1.field_1,
main_table.field_1,
main_table.field_2,
main_table.field_3,
main_table.field_4,
main_table.field_5,
main_table.field_6,
main_table.field_7,
sub_table_2.field_1,
sub_table_2.field_2,
sub_table_2.field_3,
sub_table_3.field_1,
sub_table_4.field_1,
sub_table_4.field_2
FROM main_table
INNER JOIN sub_table_4 ON sub_table_4.id = main_table.id
INNER JOIN sub_table_2 ON sub_table_2.id = main_table.id
INNER JOIN sub_table_3 ON sub_table_3.id = main_table.id
INNER JOIN sub_table_1 ON sub_table_1.id = main_table.id
WHERE sub_table_4.field_1 = '' AND sub_table_4.field_2 = '0' AND sub_table_2.field_1 != ''
The query works, the problem I have is sub_table_1 has a revision number (int 11). Currently I get duplicate records with different revision numbers and different versions of sub_table_1.field_1 which is to be expected, but I want to limit the result set to only include results limited by the latest revision number, giving me only the latest sub_table_1_field_1 and I really can not figure it out!
Can anybody lend me a hand?
Many Thanks.
It's always important to remember that a JOIN can be on a subquery as well as a table. You could build a subquery that returns the results you want to see then, once you've got the data you want, join it in the parent query.
It's hard to 'tailor' an answer that's specific to you problem, as it's too obfuscated (as you admit) to know what the data and tables really look like, but as an example:
Say table1 has four fields: id, revision_no, name and stuff. You want to return a distinct list of name values, with their latest version of stuff (which, we'll pretend varies by revision). You could do this in isolation as:
select t.* from table1 t
inner join
(SELECT name, max(revision_no) maxr
FROM table1
GROUP BY name) mx
on mx.name = t.name
and mx.maxr = t.revision_no;
(Note: see fiddle at the end)
That would return each individual name with the latest revision of stuff.
Once you've got that nailed down, you could then swap out
INNER JOIN sub_table_1 ON sub_table_1.id = main_table.id
....with....
INNER JOIN (select t.* from table1 t
inner join
(SELECT name, max(revision_no) maxr
FROM table1
GROUP BY name) mx
on mx.name = t.name
and mx.maxr = t.revision_no) sub_table_1
ON sub_table_1.id = main_table.id
...which would allow a join with a recordset that is more tailored to that which you want to join (again, don't get hung up on the actual query I've used, it's just there to demonstrate the method).
There may well be more elegant ways to achieve this, but it's sometimes good to start with a simple solution that's easier to replicate, then simplify it once you've got the general understanding of the what and why nailed down.
Hope that helps - as I say, it's as specific as I could offer without having an idea of the real data you're using.
(for the sake of reference, here is a fiddle with a working version of the above example query)
In your case where you only need one column from the table, make this a subquery in your select clause instead of than a join. You get the latest revision by ordering by revision number descending and limiting the result to one row.
SELECT
main_table.id,
(
select sub_table_1.field_1
from sub_table_1
where sub_table_1.id = main_table.id
order by revision_number desc
limit 1
) as sub_table_1_field_1,
main_table.field_1,
...
FROM main_table
INNER JOIN sub_table_4 ON sub_table_4.id = main_table.id
INNER JOIN sub_table_2 ON sub_table_2.id = main_table.id
INNER JOIN sub_table_3 ON sub_table_3.id = main_table.id
WHERE sub_table_4.field_1 = ''
AND sub_table_4.field_2 = '0'
AND sub_table_2.field_1 != '';

Grouping method

I am working on a query with the following format:
I require all the columns from the Database 'A', while I only require the summed amount (sum(amount)) from the Database 'B'.
SELECT A.*, sum(B.CURTRXAM) as 'Current Transaction Amt'
FROM A
LEFT JOIN C
ON A.Schedule_Number = C.Schedule_Number
LEFT JOIN B
ON A.DOCNUMBR = B.DOCNUMBR
ON A.CUSTNMBR = B.CUSTNMBR
GROUP BY A
ORDER BY A.CUSTNMBR
My question is regarding the grouping statement, database A has about 12 columns and to group by each individually is tedious, is there a cleaner way to do this such as:
GROUP BY A
I am not sure if a simpler way exists as I am new to SQL, I have previously investigated GROUPING_ID statements but thats about it.
Any help on lumped methods of grouping would be helpful
Since the docnumber is the primary key - just use the following SQL:
SELECT A.*, sum(B.CURTRXAM) as 'Current Transaction Amt'
FROM A
LEFT JOIN C
ON A.Schedule_Number = C.Schedule_Number
LEFT JOIN B
ON A.DOCNUMBR = B.DOCNUMBR
ORDER BY RM20401.CUSTNMBR
GROUP BY A.DOCNUMBR

SQL Server Query some specific condition

SELECT distinct t1.vssyspackageid,CA.rAmount as Amount,Curr.vsShortCode AS Currency
from tblPrograms
INNER JOIN tblProgramsAndPackages ON tblPrograms.vsSysProgramId = tblProgramsAndPackages.vsSysProgramId
inner join tblPackages t1 on tblProgramsAndPackages.iPackageId=t1.iPackageId
right join tblPkgContractAwardDetails as CA on CA.iPackageId=t1.iPackageId
join tblCurrencies as Curr on CA.iCurrency =Curr.iCurrencyId
where tblPrograms.vsSysProgramId='JICA'
group by t1.vssyspackageid,CA.rAmount,Curr.vsShortCode
if which package assigned to Contractor Award Detail then it will show in one column.
Example: GWSSP/01,GWSSP/02 then after it it shows total package in next column.
I'm not sure exactly what you are wanting as your question is a little vague, but I'm guessing that you want a single row for the specified Package that will show the sum of the Amount column. This is what I can understand from your question anyway!
SELECT DISTINCT t1.vssyspackageid,
SUM(CA.rAmount) AS TotalAmount,
Curr.vsShortCode AS Currency
FROM tblPrograms
INNER JOIN tblProgramsAndPackages ON tblPrograms.vsSysProgramId =
tblProgramsAndPackages.vsSysProgramId
INNER JOIN tblPackages AS t1 ON tblProgramsAndPackages.iPackageId =
t1.iPackageId
RIGHT JOIN tblPkgContractAwardDetails AS CA ON CA.iPackageId =
t1.iPackageId
JOIN tblCurrencies AS Curr ON CA.iCurrency =
Curr.iCurrencyId
WHERE tblPrograms.vsSysProgramId = 'JICA'
AND t1.[YOUR_COLUMN_NAME_HERE] = 'GWSSP/01'
GROUP BY t1.vssyspackageid,
Curr.vsShortCode
Just a few things to note:
I don't know the column name in the tblPackages table that the values such as 'GWSSP/01' belongs, so I have left that for you to fill in.
You will still get multiple rows if there are multiple currencies for your package, you will have to remove the Curr.vsShortCode from your Select and Group By clauses if that is the case.
I also tided up your code a bit because it was quite messy and hard to understand as well as using multiple standards and short-cuts!

Optimizing a where statement MYSQL

Im writing this complex query to return a large dataset, which is about 100,000 records. The query runs fine until i add in this OR statement to the WHERE clause:
AND (responses.StrategyFk = strategies.Id Or responses.StrategyFk IS
Null)
Now i understand that by putting the or statement in there it adds a lot of overhead.
Without that statement and just:
AND responses.StrategyFk = strategies.Id
The query runs within 15 seconds, but doesn't return any records that didn't have a fk linking a strategie.
Although i would like these records as well. Is there an easier way to find both records with a simple where statement? I can't just add another AND statement for null records because that will break the previous statement. Kind of unsure of where to go from here.
Heres the lower half of my query.
FROM
responses, subtestinstances, students, schools, items,
strategies, subtests
WHERE
subtestinstances.Id = responses.SubtestInstanceFk
AND subtestinstances.StudentFk = students.Id
AND students.SchoolFk = schools.Id
AND responses.ItemFk = items.Id
AND (responses.StrategyFk = strategies.Id Or responses.StrategyFk IS Null)
AND subtests.Id = subtestinstances.SubtestFk
try:
SELECT ... FROM
responses
JOIN subtestinstances ON subtestinstances.Id = responses.SubtestInstanceFk
JOIN students ON subtestinstances.StudentFk = students.Id
JOIN schools ON students.SchoolFk = schools.Id
JOIN items ON responses.ItemFk = items.Id
JOIN subtests ON subtests.Id = subtestinstances.SubtestFk
LEFT JOIN strategies ON responses.StrategyFk = strategies.Id
That's it. No OR condition is really needed, because that's what a LEFT JOIN does in this case. Anywhere responses.StrategyFk IS NULL will result in no match to the strategies table, and it wil return a row for that.
See this link for a simple explanation of joins: http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html
After that, if you're still having performance issues then you can start looking at the EXPLAIN SELECT ... ; output and looking for indexes that may need to be added. Optimizing Queries With Explain -- MySQL Manual
Try using explicit JOINs:
...
FROM responses a
INNER JOIN subtestinstances b
ON b.id = a.subtestinstancefk
INNER JOIN students c
ON c.id = b.studentfk
INNER JOIN schools d
ON d.id = c.schoolfk
INNER JOIN items e
ON e.id = a.itemfk
INNER JOIN subtests f
ON f.id = b.subtestfk
LEFT JOIN strategies g
ON g.id = a.strategyfk