Pivot result returning duplicate rows - sql-server-2008

With this query, I am getting result with null values and duplicate Ids...
SELECT QuesId,QuesName,[Ketan Mevada],[Parvej],[Parvez Vahora]
FROM (
SELECT tbl_EvolutionAnswer.QuesId,tbl_QuestionMaster.Name as QuesName,
dbo.Evaluation_Calculation_CourseWise(tbl_EvolutionAnswer.QuesId,34,'Course-Green Course-2045',1065, tbl_EvolutionAnswer.TrainerId ) as Average,
tbl_EvolutionAnswer.TrainerId,
tbl_TrainerMaster.Name as TrName
from tbl_EvolutionAnswer
inner join tbl_TrainerMaster
on tbl_EvolutionAnswer.TrainerId = tbl_TrainerMaster.Id
inner join tbl_QuestionMaster
on tbl_EvolutionAnswer.QuesId = tbl_QuestionMaster.QuestionId
where tbl_EvolutionAnswer.EvolId =34
and tbl_EvolutionAnswer.TrainerId <> 0
and tbl_EvolutionAnswer.CourseId = 'Course-Green Course-2045'
and tbl_EvolutionAnswer.SchID = 1065
) as Books
PIVOT (
MAX(Average) FOR TrName IN ([Ketan Mevada],[Parvej],[Parvez Vahora])
) as Result
I need Following Output
QuesId QuesName Ketan Mevada Parvej Parvez Vohra
122 Did your trainer answer... 2 3 2
123 was your trainer activ.. 1 4 3

It appears that you have a column inside your subquery that is unique and it is causing the grouping of the aggregate function to be skewed. When you are using the PIVOT function, you should only include the columns needed for the PIVOT and the final select list, otherwise you run the risk of the end result being spilt over multiple rows.
It looks like the column you need to remove is tbl_EvolutionAnswer.TrainerId. Making your actual query:
SELECT QuesId,QuesName,[Ketan Mevada],[Parvej],[Parvez Vahora]
FROM
(
SELECT tbl_EvolutionAnswer.QuesId,
tbl_QuestionMaster.Name as QuesName,
dbo.Evaluation_Calculation_CourseWise(tbl_EvolutionAnswer.QuesId,34,'Course-Green Course-2045',1065, tbl_EvolutionAnswer.TrainerId ) as Average,
tbl_TrainerMaster.Name as TrName
from tbl_EvolutionAnswer
inner join tbl_TrainerMaster
on tbl_EvolutionAnswer.TrainerId = tbl_TrainerMaster.Id
inner join tbl_QuestionMaster
on tbl_EvolutionAnswer.QuesId = tbl_QuestionMaster.QuestionId
where tbl_EvolutionAnswer.EvolId =34
and tbl_EvolutionAnswer.TrainerId <> 0
and tbl_EvolutionAnswer.CourseId = 'Course-Green Course-2045'
and tbl_EvolutionAnswer.SchID = 1065
) as Books
PIVOT (
MAX(Average) FOR TrName IN ([Ketan Mevada],[Parvej],[Parvez Vahora])
) as Result

Related

SQL - Divide One Query by Another

I am trying to create a query which returns the workout percentage completion...
Workout Percentage Completion =
((Sum of LogEntries WHERE date = IN list of dates and WorkoutID =1 ) /
(Sum of all set numbers WHERE WorkoutID = 1))
x 100
Below is what I currently have, at the moment it is only returning the result of the first query.
What should I change for the query to run correctly?
SELECT
(
(
SELECT COUNT(LogEntriesID)
FROM LogEntriesTable
LEFT JOIN ExerciseWorkoutJunctionTable
ON ExerciseWorkoutJunctionTable.ExerciseWorkoutJunctionID =
LogEntriesTable.JunctionID
WHERE LogEntriesTable.date IN (
"14-05-2020", "15-05-2020", "16-05-2020", "17-05-2020",
"18-05-2020", "19-05-2020", "20-05-2020"
)
AND ExerciseWorkoutJunctionTable.WorkoutID = 1
) / (
SELECT sum(SetNumber)
FROM ExerciseWorkoutGoalsTable
LEFT JOIN ExerciseWorkoutJunctionTable
ON ExerciseWorkoutJunctionTable.ExerciseWorkoutJunctionID =
ExerciseWorkoutGoalsTable.JunctionID
WHERE ExerciseWorkoutJunctionTable.WorkoutID = 1
)
)
Your first SELECT statement is doing an OUTER JOIN but then you have a WHERE clause that is selecting non-NULL values from the ExerciseWorkoutJunctionTable table, so I suspect you might as well be doing an INNER JOIN.
When you have two queries, try:
SET #sum = (SELECT SUM(SetNumber) etc ....);
SELECT (COUNT(LogEntriesID) * 100 / #sum) AS percentage
FROM etc.
If you are using MySQL >= 8.0 you should be able to use window functions like this which breakdown your query into more readable sections.
with entries as (
SELECT COUNT(LogEntriesID) as log_entry_count
FROM LogEntriesTable as l
LEFT JOIN ExerciseWorkoutJunctionTable as e ON
e.ExerciseWorkoutJunctionID = l.JunctionID
WHERE l.date IN ("14-05-2020","15-05-2020","16-05-2020","17-05-2020","18-05-2020","19-05-2020","20-05-2020")
AND e.WorkoutID = 1
),
sets as (
SELECT sum(SetNumber) as set_sum
FROM ExerciseWorkoutGoalsTable as eg
LEFT JOIN ExerciseWorkoutJunctionTable ej
ON ej.ExerciseWorkoutJunctionID = eg.JunctionID
WHERE ej.WorkoutID = 1
)
select ((select log_entry_count from entries) / (select set_sum from sets)) * 100 as workout_completion_pct

MYSQL - CONCATENATE a lookup tables columns into one row

I have the following table structure:
tbl_catalogue_state
In tbl_catalogue there is a part number 58674 that has three states in the tbl_catalogue_state_lk table. Here is the result when I run a query inner joining the three tables.
As expected there are multiple rows returned.
Is there a way to only return one row having the values for each catalgue_state_id on the same row?
I would also like the ability to ignore a row for example:
select tbl_catalogue.catalogue_part, tbl_catalogue_state.catalogue_state_id from tbl_catalogue
inner join tbl_catalogue_state_lk on tbl_catalogue.catalogue_id = tbl_catalogue_state_lk.catalogue_id
inner join tbl_catalogue_state on tbl_catalogue_state_lk.catalogue_state_id = tbl_catalogue_state.catalogue_state_id
where tbl_catalogue_state_lk.catalogue_state_id <> 1;
The above select still returns two rows.
UPDATE
I was able to use GROUP_CONCAT:
select tbl_catalogue.catalogue_part, GROUP_CONCAT(tbl_catalogue_state.catalogue_state_id) as cat_state from tbl_catalogue
inner join tbl_catalogue_state_lk on tbl_catalogue.catalogue_id = tbl_catalogue_state_lk.catalogue_id
inner join tbl_catalogue_state on tbl_catalogue_state_lk.catalogue_state_id = tbl_catalogue_state.catalogue_state_id
where tbl_catalogue_state_lk.catalogue_state_id <> 1
group by tbl_catalogue.catalogue_id;
My issue is the above statement still returns a row. I need it to return nothing.
I was able to use not exists:
select tc.catalogue_part, GROUP_CONCAT(tcs.catalogue_state_id) as cat_state from tbl_catalogue as tc
inner join tbl_catalogue_state_lk as tcsl on tc.catalogue_id = tcsl.catalogue_id
inner join tbl_catalogue_state as tcs on tcsl.catalogue_state_id = tcs.catalogue_state_id
where
not exists
(
select tcsl2.catalogue_state_id from tbl_catalogue_state_lk as tcsl2
where tcsl2.catalogue_state_id = 6 and tcsl2.catalogue_id = tc.catalogue_id
)
and
not exists
(
select tcsl3.catalogue_state_id from tbl_catalogue_state_lk as tcsl3
where tcsl3.catalogue_state_id = 1 and tcsl3.catalogue_id = tc.catalogue_id
)
and
not exists
(
select tcsl3.catalogue_state_id from tbl_catalogue_state_lk as tcsl3
where tcsl3.catalogue_state_id = 2 and tcsl3.catalogue_id = tc.catalogue_id
)
group by tc.catalogue_id;

mysql combine 2 queries from same table

This is query 1:
SELECT distinct c.chem_gene, m.String_name, m.ScopeNote
FROM mesher m INNER JOIN chem_base c
ON (c.chem_name = m.String_name AND m.ScopeNote <> '' )
where match (c.chem_gene) against('ACTN3, MTHFR' in boolean mode)
group by c.chem_gene, c.chem_name;
which outputs 3 columns in rows like this:
'ACTN3', 'Estradiol', 'The 17-beta-isomer of estradiol...'
This is query 2 (taking the output from column 2, "Estradiol"):
SELECT String10 FROM mesher where String_name = "Estradiol" AND String10 <>'' LIMIT 1;
which outputs a single row in a single column:
'Estrogens'
How can I modify query 1 so that for each row returned the additional query is made against the result in the second column (i.e.'Estradiol') to produce this output:
'ACTN3', 'Estradiol', 'The 17-beta-isomer of estradiol...', 'Estrogens'
If I understand correctly, you can use a correlated subquery:
SELECT c.chem_gene, m.String_name, m.ScopeNote,
(SELECT mm.String10
FROM mesher mm
WHERE mm.String_name = m.String_name AND mm.String10 <> ''
LIMIT 1
)
FROM mesher m INNER JOIN
chem_base c
ON c.chem_name = m.String_name AND m.ScopeNote <> ''
WHERE match(c.chem_gene) against( 'ACTN3, MTHFR' in boolean mode)
GROUP BY c.chem_gene, c.chem_name, m.ScopeNote ;
The select distinct is not necessary.

Not able to get the required ID's from a MySQL GROUP BY + HAVING query

I'm using a query various IN() clauses to get the price of product combinations. I am actually correctly getting the prices, so thats OK. But I also need some other ID's to identify to which ID's the prices belong.
As you can see IN's, they all start with a different bundle_variant_id's but the rest of the bundle_variant_id's are the same. I want to return that first (or all) of those bundle_variant_id's in the result too, but using this query, i always get '1620' as bundle_variant_id. How can i get the first bundle_variant_id in those IN's (1616, 1655, 1677, etc) or ALL of the bundle_variant_id's?
It's not an option to remove the GROUP and the HAVING or any of the WHERE clauses.
SELECT `HardwareProductSubscriptionInstanceLink`.`subscription_instance_id`
,`BundleVariantLink`.`bundle_variant_id`
,`HardwareProductSubscriptionInstanceLink`.`price`
FROM `wax`.`prd_providers` AS `Provider`
INNER JOIN `wax`.`prd_subscription_types` AS `SubscriptionType` ON (`SubscriptionType`.`provider_id` = `Provider`.`id`)
INNER JOIN `wax`.`prd_subscriptions` AS `Subscription` ON (`Subscription`.`subscription_type_id` = `SubscriptionType`.`id`)
INNER JOIN `wax`.`prd_subscription_instances` AS `SubscriptionInstance` ON (`SubscriptionInstance`.`subscription_id` = `Subscription`.`id`)
INNER JOIN `wax`.`prd_bundle_variants_subscription_instances` AS `BundleVariantLink` ON (`BundleVariantLink`.`subscription_instance_id` = `SubscriptionInstance`.`id`)
INNER JOIN `wax`.`prd_hardware_products_subscription_instances` AS `HardwareProductSubscriptionInstanceLink` ON (
`HardwareProductSubscriptionInstanceLink`.`subscription_instance_id` = `SubscriptionInstance`.`id`
AND `HardwareProductSubscriptionInstanceLink`.`hardware_product_id` = 317
)
WHERE (
(
`BundleVariantLink`.`bundle_variant_id` IN (
'1616'
,'1618'
,'1600'
,'1620'
)
)
OR (
`BundleVariantLink`.`bundle_variant_id` IN (
'1655'
,'1618'
,'1600'
,'1620'
)
)
OR (
`BundleVariantLink`.`bundle_variant_id` IN (
'1677'
,'1618'
,'1600'
,'1620'
)
)
OR (
`BundleVariantLink`.`bundle_variant_id` IN (
'1691'
,'1618'
,'1600'
,'1620'
)
)
AND `SubscriptionInstance`.`number_of_bundle_variants` = 4
AND (
(`Provider`.`enabled` = '1')
AND (`Provider`.`visible` = '1')
)
GROUP BY `SubscriptionInstance`.`id`
HAVING count(`BundleVariantLink`.`bundle_variant_id`) = 4
Current results:
(column 1 = subscription_instance_id, 2=bundle_variant_id,3=price)
9213 1620 331.405
9214 1620 311.57
9215 1620 291.736
9219 1620 390.909
Required results:
9213 1616 331.405
9214 1655 311.57
9215 1677 291.736
9219 1691 390.909
Or alternate required results:
9213 1616,1618,1600,1620 331.405
9214 1655,1618,1600,1620 311.57
9215 1677,1618,1600,1620 291.736
9219 1691,1618,1600,1620 390.909

SQL Query behavior

I'm bogged in trying to figure out why query a is returning different records than query b. Both queries have seemingly same purpose yet a is returning 500 and b 3500.
this is query a:
SELECT DISTINCT ODE.OrderBillToID
FROM APTIFY.dbo.vwVwOrderDetailsKGExtended ODE
WHERE ProductID IN (2022, 1393)
AND LTRIM(RTRIM(ODE.OrderStatus)) <> 'Cancelled'
AND LTRIM(RTRIM(ODE.OrderType)) <> 'Cancellation'
AND LTRIM(RTRIM(ODE.cancellationStatus)) <> 'FULLY CANCELLED'
UNION
SELECT DISTINCT ID
FROM APTIFY.dbo.vwPersons WHERE City = 'A'
UNION
SELECT DISTINCT RecordID
FROM APTIFY.dbo.vwTopicCodeLinks WHERE TopicCodeID = 16 AND Value = 'Yes, Please'
query b:
SELECT
APTIFY..vwPersons.ID
FROM
APTIFY..vwPersons
WHERE
( APTIFY..vwPersons.ID IN (
SELECT
vwMeetingRegistrants.ID
FROM
APTIFY.dbo.vwMeetings vwMeetings
INNER JOIN APTIFY.dbo.vwMeetingRegistrants vwMeetingRegistrants
ON vwMeetings.ID=vwMeetingRegistrants.ActualMeetingID WHERE
vwMeetings.ProductID = 2022
)
OR
APTIFY..vwPersons.ID IN (
SELECT
vwMeetingRegistrants.ID
FROM
APTIFY.dbo.vwMeetings vwMeetings
INNER JOIN APTIFY.dbo.vwMeetingRegistrants vwMeetingRegistrants
ON vwMeetings.ID=vwMeetingRegistrants.ActualMeetingID WHERE
vwMeetings.ProductID = 1393
)
OR
APTIFY..vwPersons.City = N'Albany' )
OR
((
APTIFY..vwPersons.ID IN (
SELECT
RecordID
FROM
APTIFY.dbo.vwTopicCodeLinks vwTopicCodeLinks
WHERE
vwTopicCodeLinks.TopicCodeID = 16
)
AND
APTIFY..vwPersons.ID IN (
SELECT
RecordID
FROM
APTIFY.dbo.vwTopicCodeLinks vwTopicCodeLinks
WHERE
vwTopicCodeLinks.Value = N'Yes, Please'
) )
)
vwMeetingsRegistrants from the b query are producing the same records as orderkgdetailsextended from query. I cannot see ANY difference in those queries - which perhaps shows my lack of understanding the query behaviour.
BIG Thanks for any points guys! :)
As it came out, incorrectly structured query is a result of badly configured application, Aptify.