SQL Comparing 2 values that must be determined - mysql

I need to Find out the course with the most passes from my table tblResults.
tblResults:
StuID Course Symbol
1001 CSC101 P
1001 RNG101 F
1002 CSC101 P
1002 RNF101 F
1003 HAP101 P
1004 HAP101 P
i.e should give CSC101 (And all other courses (HAP101) with the same ammount of passes)
I have tried:
CREATE VIEW Part1 AS
SELECT NumbF
FROM
(SELECT COUNT(Course) AS NumbP,
Course
FROM tblResults
WHERE Symbol = 'P')
GROUP BY Course);
CREATE VIEW Part2 AS
SELECT MAX(NumbP) AS Maxnum
FROM Part1,
tblResults
WHERE Symbol = 'P'
GROUP BY Course;
SELECT Part1.Course
FROM Part1,
Part2
WHERE Part1.NumbP = Part2.MaxNum
But I seem to be doing something incorrectly. Please help

Something like this should work:
create view yourview as
select course, count(*) passcnt
from tblResults
where symbol = 'P'
group by course
select *
from yourview
where passcnt = (select max(passcnt) from yourview)
SQL Fiddle Demo
Note, you don't need the view, I just left it for simplicity.

SELECT Course, count(StuID) count
FROM tblResults
GROUP BY Course
HAVING count = (SELECT max(c)
FROM (SELECT count(StuID) c, Course
FROM tblResults
GROUP BY Course
WHERE Symbol = 'p'
) counts
);

You can try the SELECT below, but I haven't tested it:
SELECT selA.Course, selA.NumPass FROM (
SELECT Course, COUNT(Course) AS NumPass FROM
tblResults GROUP BY Course HAVING Symbol = 'P') AS selA
INNER JOIN (
SELECT MAX(NumPassCount) AS NumPassMax FROM (
SELECT COUNT(Course) AS NumPassCount FROM
tblResults GROUP BY Course HAVING Symbol = 'P') AS selB)
AS selC ON selA.NumPass = selC.NumPassMax

Using a couple of sub queries
SELECT Sub3.Course
FROM
(
SELECT MAX(Course) AS MaxCourseCnt
FROM
(
SELECT Course, COUNT(*) AS CourseCnt
FROM tblResults
WHERE Symbol = 'P'
GROUP BY Course
) Sub1
) Sub2
INNER JOIN
(
SELECT Course, COUNT(*) AS CourseCnt
FROM tblResults
WHERE Symbol = 'P'
GROUP BY Course
) Sub3
ON Sub2.MaxCourseCnt = Sub3.CourseCnt

Related

Update values that have something in common

I´m trying to set a value for those pets who share a owner.
update Pets
set multiple = 1
where Phone_owner in (
SELECT *
FROM (
SELECT Phone_owner, COUNT(*) Total
FROM Pets
GROUP BY Phone_owner
HAVING COUNT(*) > 1
) a
);
I get this error:
Error Code: 1241. Operand should contain 1 column(s)
Use a JOIN rather than WHERE ... IN
UPDATE Pets AS p1
JOIN (
SELECT Phone_owner
FROM Pets
GROUP BY Phone_owner
HAVING COUNT(*) > 1
) AS p2 ON p1.Phone_owner = p2.Phone_owner
SET p1.multiple = 1

SQL query to select a value based on certain criteria

I have the following data in my Database:
Id MachineName CategoryName CounterName InstanceName RawValue
11180 SERVER64 Process ID Process w3wp#2 2068
11180 SERVER64 Process Working Set w3wp#2 9310208
Now I want to achieve that if I find the value '2068' for the "ID Process" Countername then I want to retrieve the Working Set RawValue. So based on the value of ID Process I now the [InstanceName] = w3wp#2 and therefore I want the value to retrieve = 9310208
Now I tried different SQL queries:
SELECT *
FROM [dbo].[LoadTest]
WHERE [LoadTestRunId] = '11180' and [CategoryName] = 'Process' and [InstanceName] like 'w3wp%'
But I need a filter. Can anyone guide me into the right direction?
This here will help you. I used variable because you need to find a specific ID
SQL Code
declare #myt table (id int,MachineName nvarchar(50),CategoryName nvarchar(50),CounterName nvarchar(50),InstanceName nvarchar(50),RawValue int)
insert into #myt
values
(11180 ,'SERVER64','Process','ID Process','w3wp#2',2068),
(11180 ,'SERVER64','Process','Working Set','w3wp#2',9310208)
declare #FindID int
Set #FindID = 2068;
with IdProcess as (
Select * from #myt
where RawValue = #FindID and CounterName = 'ID Process'
)
Select a.ID,a.MachineName,a.CategoryName,b.CounterName,a.InstanceName,b.RawValue from IdProcess a
inner join #myt b on a.InstanceName = b.InstanceName and b.CounterName='Working Set'
SQL Code without variable based on ID and InstanceName
with IdProcess as (
Select * from #myt
where CounterName = 'ID Process'
)
Select a.ID,a.MachineName,a.CategoryName,b.CounterName,a.InstanceName,b.RawValue from IdProcess a
inner join #myt b on a.id = b.id and a.InstanceName = b.InstanceName and b.CounterName='Working Set'
SQL Code with CategoryName filter
with IdProcess as (
Select * from #myt
where CounterName = 'ID Process' and CategoryName = 'Process'
)
Select a.ID,a.MachineName,a.CategoryName,b.CounterName,a.InstanceName,b.RawValue from IdProcess a
inner join #myt b on a.id = b.id and a.InstanceName = b.InstanceName and b.CounterName='Working Set'
where b.CategoryName = 'Process'
Result
This will execute.
Select * from (SELECT ROW_NUMBER() OVER(PARTITION BY LoadTestRunId ORDER BY LoadTestRunId DESC) as row,*
FROM [dbo].[LoadTest]) t1 where row=1
with your where clause
Select * from (SELECT ROW_NUMBER() OVER(PARTITION BY LoadTestRunId ORDER BY LoadTestRunId DESC),*
FROM [dbo].[LoadTest]) t1 where t1=1
and [LoadTestRunId] = '11180' and [CategoryName] = 'Process' and [InstanceName] like 'w3wp%'

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.

Select only having count=2

--This is the code
create table #Test (Systemtraceno nvarchar(50),Bin nvarchar(50),SwitchCode nvarchar(50),
SwitchDesc nvarchar(50),[Description] nvarchar(50))
insert into #Test
select SystemTraceno , Bin,SwitchCode,SwitchDesc,[Description]
from(
select A.SystemTraceNo, A.BIN,'' SwitchCode, '' SwitchDesc,''[Description]
from ATM035 A
where a.TranDate = '20130924' and MsgType = '0210' and TerminalID = '08880001'
and A.ProcessCode in ('011000','012000','013000') and A.ResponseCode = '0000' and A.BIN <> '502265'
--group by A.SystemTraceNo, A.BIN
)x
group by SystemTraceNo,BIN,SwitchCode,SwitchDesc,[Description]
having COUNT(SystemTraceNo)=2
update #Test set SwitchCode = (select top 1 SwitchCode from ATM027 where Bin = #Test.Bin )
update #test set SwitchDesc = (select switchname from ATM016 where SwitchCode = #test.switchcode)
update #test set [Description] = (Select top 1 Description from ATM027 where BIN = #Test.Bin )
Select * from #test order by SwitchDesc asc
drop table #test
--,'301000','302000','303000'
i just wanted to select rows having SystemTrace number count = 2.I earlier had problems with aggregation and now this.Hoping you could help me out.Thanks in advance
#Royi: actually, i think it should be
select customers.customerId , count(orders.id) as num
from customers join orders on custumers.Id = orders.customerId
group by customers.customerId
having num=2
I'm not going to get into your code but this is how it should be :
select customers.customerId
from customers join orders on custumers.Id = orders.customerId
group by customers.customerId
having count(orders.id)=2
See section 2 here : (section 1 is for the one who said it's possible).
http://i.stack.imgur.com/aE2M3.png
where systemtraceno in (select systemtraceno from #Test group by systemtraceno having count(systemtraceno) = 2)
I thin the problem is at
group by SystemTraceNo
when you want to use
COUNT(SystemTraceNo)=2
In short your insert code should be like this:
insert into #Test
select A.SystemTraceno , A,Bin,'' SwitchCode,'' SwitchDesc,'' [Description]
from ATM035 A
where a.TranDate = '20130924' and MsgType = '0210' and TerminalID = '08880001'
and A.ProcessCode in ('011000','012000','013000') and A.ResponseCode = '0000' and A.BIN <> '502265'
group by A.BIN
having COUNT(SystemTraceNo)=2

How to select all this data without repeating subqueries?

Say I have a table called 'users', a table called 'posts' and a table called 'ratings', that stores the rating of each user to each post. If I wanted to select the posts, together with their thumbs up, thumbs down and 'average' ratings (rounded to the second decimal), I would do:
SELECT *,
(SELECT COUNT(*) FROM ratings WHERE thumb='up' AND post_id = posts.id) AS thumbs_up,
(SELECT COUNT(*) FROM ratings WHERE thumb='down' AND post_id = posts.id) AS thumbs_down,
ROUND((SELECT COUNT(*) FROM ratings WHERE thumb='up' AND post_id = posts.id) / (SELECT COUNT(*) FROM ratings WHERE post_id = posts.id), 2) AS average_rating
FROM posts;
But is there a way to obtain this same data without repeating the subqueries? I mean, ideally I would like to do:
SELECT *,
(SELECT COUNT(*) FROM ratings WHERE thumb='up' AND post_id = posts.id) AS thumbs_up,
(SELECT COUNT(*) FROM ratings WHERE thumb='down' AND post_id = posts.id) AS thumbs_down,
ROUND(thumbs_up / (thumbs_up + thumbs_down), 2) AS average_rating
FROM posts;
But MySQL does not allow this. What is next best thing? Or is there an even better way, by using JOINs or UNIONs?
SELECT
*,
ROUND(thumbs_up / (thumbs_up + thumbs_down), 2) AS average_rating
FROM (
SELECT
YourColumns...
SUM(CASE WHEN r.thumb = 'up' THEN 1 END) AS thumbs_up,
SUM(CASE WHEN r.thumb = 'down' THEN 1 END) AS thumbs_down
FROM
posts p LEFT JOIN
ratings r ON r.post_id = p.id
GROUP BY YoursColumns
) sub
Why not having in your "posts" table a column "ups" and "downs" where are summarized / counted the ups and downs ? you would end with something like this :
SELECT ups, downs, ROUND(ups / (ups + downs), 2) AS average_rating FROM posts where id = anId;
You could simply use variables inside a stored procedure. Code is concept and may need adjustment to fit mysql.
SET #thumbsup = 0;
SET #thumbsdown = 0;
SELECT #thumbsup = COUNT( * ) FROM ratings WHERE thumb = 'up' AND post_id = #someid;
SELECT #thumbsdown = COUNT( * ) FROM ratings WHERE thumb = 'down' AND post_id = #someid;
RETURN #thumbsup, #thumbsdown, ROUND( #thumbsup / ( thumbsup + thumbsdown ), 2 );