Julia asked her students to create some coding challenges. Write a query to print the hacker_id, name, and the total number of challenges created by each student. Sort your results by the total number of challenges in descending order. If more than one student created the same number of challenges, then sort the result by hacker_id. If more than one student created the same number of challenges and the count is less than the maximum number of challenges created, then exclude those students from the result.
Input Format
The following tables contain challenge data:
Hackers: The hacker_id is the id of the hacker, and name is the name of the hacker.
Hackers Table
Challenges: The challenge_id is the id of the challenge, and hacker_id is the id of the student who created the challenge.
Challenges Table
here is the query that i wrote
select H.hacker_id,H.name,T.challenges_created
from Hackers H join
(SELECT hacker_id ,
COUNT(Challeneges.challenge_id) as challenges_created
FROM Challenges
GROUP BY hacker_id
HAVING challenges_created >= max(challenges_created)
) T
on H.hacker_id=T.hacker_id
ORDER BY T.challenges_created desc, H.hacker_id asc
but i'm getting error saying that
Msg 207, Level 16, State 1, Server WIN-ILO9GLLB9J0, Line 12 Invalid
column name 'challenges_created'. Msg 207, Level 16, State 1, Server
WIN-ILO9GLLB9J0, Line 12 Invalid column name 'challenges_created'.
Msg 4104, Level 16, State 1, Server WIN-ILO9GLLB9J0, Line 9 The
multi-part identifier "Challeneges.challenge_id" could not be bound.
Line 9 The multi-part identifier "Challeneges.challenge_id" could not be bound.
Looks like you spelt Challenges wrong.
select C.Hacker_id, H.Name, count(challenge_id)
from Hackers H Inner Join Challenges C
ON H.Hacker_Id = C.Hacker_Id
group by C.Hacker_Id, H.Name
having count(challenge_id) not in (select x.ChallengeCount from (
select C.Hacker_id, H.Name, count(challenge_id) as ChallengeCount
from Hackers H Inner Join Challenges C
ON H.Hacker_Id = C.Hacker_Id
group by C.Hacker_Id, H.Name
) x
where x.ChallengeCount <> (select top 1 count(challenge_id) from Challenges group by hacker_Id order by 1 desc)
group by x.ChallengeCount
having count(x.challengecount) > 1)
order by 3 desc, 1
WITH TEMP AS
(
SELECT H.HACKER_ID AS HID,
H.NAME AS HNAME,
COUNT(C.CHALLENGE_ID) AS CNT
FROM HACKERS
JOIN CHALLENGES C
ON H.HACKER_ID=C.HACKER_ID
GROUP BY H.HACKER_ID,H.NAME
)
SELECT * FROM TEMP
WHERE CNT IN
( SELECT CNT FROM TEMP count challenges
GROUP BY CNT
HAVING COUNT(CNT)=1
) OR CNT=(SELECT MAX(CNT) FROM TEMP)
ORDER BY CNT DESC,HID
SELECT c.hacker_id, h.name, COUNT(c.challenge_id) AS cnt
FROM Hackers h, Challenges c
where h.hacker_id = c.hacker_id
GROUP BY c.hacker_id, h.name
HAVING
count(c.challenge_id) = (SELECT max(COUNT(c1.challenge_id)) FROM Challenges c1
GROUP BY c1.hacker_id)
OR
count(c.challenge_id) NOT IN (SELECT COUNT(c2.challenge_id) FROM Challenges c2
GROUP BY c2.hacker_id
HAVING c2.hacker_id <> c.hacker_id)
ORDER BY cnt DESC, c.hacker_id;
This not so complex logic might be easier to understand;
WITH now AS (SELECT hacker_id AS hi, COUNT(*) AS nmbr,
COUNT(COUNT(*)) OVER(PARTITION BY COUNT(*)) AS ccnt
FROM challenges
GROUP BY hacker_id)
SELECT n.hi, h.name, n.nmbr
FROM now AS n, hackers AS h
WHERE (n.nmbr = (SELECT MAX(nmbr) FROM now) OR n.ccnt = 1)
AND n.hi = h.hacker_id
ORDER BY n.nmbr DESC, n.hi
;
select ch.hacker_id,h.name,count(ch.challenge_id) as challenges_created
from hackers h
join
challenges ch
on
h.hacker_id=ch.hacker_id
group by ch.hacker_id,h.name
having count(ch.challenge_id)in (select max(a.cnt) from (select count(challenge_id) as cnt from challenges group by hacker_id)a)
union
select ch.hacker_id,h.name,count(ch.challenge_id) as challenges_created
from hackers h
join
challenges ch
on
h.hacker_id=ch.hacker_id
group by ch.hacker_id,h.name
having count(ch.challenge_id)IN(select c.chlng from (select b.chlng, count(*) as cnt from (select hacker_id,count(challenge_id) as chlng from challenges group by hacker_id)b group by b.chlng) c where c.cnt=1)
order by challenges_created desc, ch.hacker_id
with cte as(
select a.hacker_id,a.name,count(b.challenge_id) as challange,COUNT(COUNT(b.challenge_id)) OVER(PARTITION BY COUNT(b.challenge_id)) as rank_
from Hackers as a inner join Challenges as b
on a.hacker_id = b.hacker_id
group by a.hacker_id,a.name
) select hacker_id,name,challange from cte
where rank_>1 and challange=(select max(challange) from cte) or rank_ =1
order by challange desc,hacker_id
This is my answer to the question
with cte as
(
select h.hacker_id, h.name, count(c.challenge_id) counts
from hackers h inner join challenges c on c.hacker_id = h.hacker_id
group by h.hacker_id, h.name
)
select
a.hacker_id, a.name, a.counts
from
cte a
inner join (select count(1) rankie, counts from cte b group by counts) b on a.counts= b.counts
cross join ( select max(counts) maxCount from cte) c
where 1=1
and (a.counts < c.maxCount
and rankie <=1)
or a.counts = c.maxCount
order by a.counts desc, a.hacker_id desc
Normally you can't refer to field aliases in the HAVING clause
Instead use
COUNT(Challeneges.challenge_id)
You can also try this
SELECT h.hacker_id,
h.name,
COUNT(c.challenge_id) AS challenge_count
FROM Hackers h
JOIN Challenges c ON c.hacker_id = h.hacker_id
GROUP BY h.hacker_id, h.name
HAVING challenge_count =
(SELECT COUNT(challenge_id) AS count_max
FROM Challenges
GROUP BY hacker_id
ORDER BY count_max DESC limit 1)
OR challenge_count IN
(SELECT DISTINCT c_compare AS c_unique
FROM (SELECT h2.hacker_id,
h2.name,
COUNT(challenge_id) AS c_compare
FROM Hackers h2
JOIN Challenges c ON c.hacker_id = h2.hacker_id
GROUP BY h2.hacker_id, h2.name) counts
GROUP BY c_compare
HAVING COUNT(c_compare) = 1)
ORDER BY challenge_count DESC, h.hacker_id;
In my code I haven't use aliases thus it is not showing any errors.
Related
I have the following query:
I am trying to select for each ACCOUNT_ID in the Table PAYMENT its maximum AMOUNT value.
It gives me a result but I suspect I am missing ACCOUNT_ID rows (I should get more ACCOUNT_ID)
SELECT a.REQUEST_DATE as PartyID, a.AMOUNT
FROM admin_all.PAYMENT a
LEFT OUTER JOIN admin_all.PAYMENT b
ON a.ACCOUNT_ID = b.ACCOUNT_ID AND a.AMOUNT < b.AMOUNT
WHERE b.ACCOUNT_ID IS NULL and a.TYPE='DEPOSIT' and a.STATUS='COMPLETED'
and (a.REQUEST_DATE between '2019-12-01' and '2019-12-17')
Can anybody indicate if my select is correct?
Maybe something like this
SELECT a.ACCOUNT_ID, MAX(a.AMOUNT)
FROM admin_all.PAYMENT a
WHERE a.TYPE='DEPOSIT' and a.STATUS='COMPLETED'
and (a.REQUEST_DATE between '2019-12-01' and '2019-12-17')
GROUP BY a.ACCOUNT_ID
--You can USE ROW_NUMBER() with OVER and PARTITION BY to break up the records
--into numbered rows ordered by the highest AMOUNT (DESC) and partitioned by the ID
--Then grab each record with a ROWNUM = 1
SELECT x.[PartyID], x.[AMOUNT]
FROM
(
SELECT a.REQUEST_DATE as PartyID, a.AMOUNT, ROW_NUMBER() OVER (PARTITION BY a.ACCOUNT_ID ORDER BY a.AMOUNT DESC) AS [RowNum]
FROM admin_all.PAYMENT a
LEFT OUTER JOIN admin_all.PAYMENT b
ON a.ACCOUNT_ID = b.ACCOUNT_ID AND a.AMOUNT < b.AMOUNT
WHERE b.ACCOUNT_ID IS NULL and a.TYPE='DEPOSIT' and a.STATUS='COMPLETED'
and (a.REQUEST_DATE between '2019-12-01' and '2019-12-17')
) AS x
WHERE x.[RowNum] = 1
I'm trying to calculate list all Customers A/C Receivables.
I calculate list of sales and receipts of customers, now I'm stuck how to calculate Receivables.
All Customer's Sales Report
Select c.StakeHolderId, c.CompanyName, sum(s.Amount) as TotalSales from
StakeHolders c
left Join Sales s on
c.StakeHolderId = s.BuyerId
where c.StakeHolderTypeId = '0b85a69e-55f2-4142-a49d-98e22aa7ca10'
group By c.StakeHolderId, c.CompanyName
All Customer's Receipts
Select c.StakeHolderId, c.CompanyName, sum(pr.Amount) as TotalReceipts
from
StakeHolders c
left Join PaymentsAndReceipts pr on
c.StakeHolderId = pr.StakeHolderId
where c.StakeHolderTypeId = '0b85a69e-55f2-4142-a49d-98e22aa7ca10'
group By c.StakeHolderId, c.CompanyName
I have tried this but didn't get the right result.
Select
c.StakeHolderId,
c.CompanyName,
sum(s.Amount) - sum(pr.Amount) as Receivables
from Sales s
right outer join StakeHolders c on
c.StakeHolderId = s.BuyerId
left outer join PaymentsAndReceipts pr on
pr.StakeHolderId = c.StakeHolderId
where c.StakeHolderTypeId = '0b85a69e-55f2-4142-a49d-98e22aa7ca10'
Group By c.StakeHolderId,c.CompanyName
expected Result:
Does this work for you?:
WITH [CalculatedData] AS
(
SELECT
C.[StakeHolderId],
C.[CompanyName],
COALESCE((SELECT SUM([Amount])
FROM [Sales]
WHERE [BuyerId] = C.[StakeHolderId]
), 0) AS [TotalSales],
COALESCE((SELECT SUM([Amount])
FROM [PaymentsAndReceipts]
WHERE [StakeHolderId] = C.[StakeHolderId]
), 0) AS [TotalReceipts]
FROM
[StakeHolders] AS C
WHERE
C.[StakeHolderTypeId] = '0b85a69e-55f2-4142-a49d-98e22aa7ca10'
)
SELECT
[StakeHolderId],
[CompanyName],
[TotalSales] - [TotalReceipts] AS [Receivables]
FROM
[CalculatedData]
Note that I include negative values in the result. If you want negative values shown between parentheses, that's possible too, but it will require conversion of numerical data to textual data in the query results. IMHO, that's not a flexible strategy (since you lose the option to perform any additional client-side calculations) and it should be the client's purpose to correctly format the values.
Edit:
If you don't like Common Table Expressions, you can convert it to a regular table expression:
SELECT
[StakeHolderId],
[CompanyName],
[TotalSales] - [TotalReceipts] AS [Receivables]
FROM
(
SELECT
C.[StakeHolderId],
C.[CompanyName],
COALESCE((SELECT SUM([Amount])
FROM [Sales]
WHERE [BuyerId] = C.[StakeHolderId]
), 0) AS [TotalSales],
COALESCE((SELECT SUM([Amount])
FROM [PaymentsAndReceipts]
WHERE [StakeHolderId] = C.[StakeHolderId]
), 0) AS [TotalReceipts]
FROM
[StakeHolders] AS C
WHERE
C.[StakeHolderTypeId] = '0b85a69e-55f2-4142-a49d-98e22aa7ca10'
) AS [CalculatedData]
just take first query LEFT JOIN to second query join by StakeHolderId & companyname. After that take sales subtract receipts
SELECT S.StakeHolderId, S.CompanyName,
Receivables = TotalSales - ISNULL(TotalReceipts , 0)
FROM
(
-- this is your first query
Select c.StakeHolderId, c.CompanyName, sum(s.Amount) as TotalSales from
StakeHolders c
left Join Sales s on
c.StakeHolderId = s.BuyerId
where c.StakeHolderTypeId = '0b85a69e-55f2-4142-a49d-98e22aa7ca10'
group By c.StakeHolderId, c.CompanyName
) S
LEFT JOIN
(
-- this is your second query
Select c.StakeHolderId, c.CompanyName, sum(pr.Amount) as TotalReceipts
from
StakeHolders c
left Join PaymentsAndReceipts pr on
c.StakeHolderId = pr.StakeHolderId
where c.StakeHolderTypeId = '0b85a69e-55f2-4142-a49d-98e22aa7ca10'
group By c.StakeHolderId, c.CompanyName
) R ON S.StakeHolderId = R.StakeHolderId
AND S.CompanyName = R.CompanyName
i need your help! I got some simple SQL skills, but this query kills me...
My Tables
Now i want the TOP5 WorkTimes on the Equipment (What Equipment got the longest WorkTime).
I want this OUTPUT:
MY Query:
SELECT
Equipment, EquipmentName, count(Equipment) as Count
FROM
Operations o
LEFT JOIN Orders ord ON ord.Id = o.[Order]
LEFT OUTER JOIN Equipments e ON ord.Equipment = e.EquipmentNumber
GROUP BY
Equipment, EquipmentName
ORDER BY Count DESC;
Another Question is how i can show o.Worktime?
i got an error with GroupBy...
please help me Thanks!
You can try this query:
select equip_nr,
(select equipmentname from table_equipments where equipmentnr = [to].equip_nr) equip_name,
sum(timeInMins) / 60.0 Worktime
from (
select (select equipmentnr from table_orders where id = [to].[order]) equip_nr,
case when workunittime = 'RH' then worktime * 60 else worktime end timeInMins
from table_operations [to]
where exists(select 1 from table_orders
where [to].[order] = id
and location = '152')
and [start] >= '2018-07-01 00:00:00.000' and [start] < '2018-08-01 00:00:00.000'
) [to] group by equip_nr
By the way, LEFT JOIN is equivalent to LEFT OUTER JOIN.
Just use SUM(worktime) as aggregate function, instead of COUNT(Equipment)
SELECT
e.[ID_Equipment]
, Name
, SUM( IIF(o.WorkUnitTime='MIN', worktime/60.0, worktime) ) as WorktimeMIN
FROM
Operations o
LEFT JOIN Orders ord ON ord.ID_Order = o.ID_Order
LEFT OUTER JOIN Equipment e ON ord.ID_Equipment = e.ID_Equipment
GROUP BY
e.[ID_Equipment]
, Name
ORDER BY
WorktimeMIN DESC
See SQL Fiddle here: http://sqlfiddle.com/#!18/5b5ed/11
I am stuck with this. I have a simple set-up with two tables. One table is holding emailaddresses one table is holding vouchercodes. I want to join them in a third table, so that each emailaddress has one random vouchercode.
Unfortunatly I am stuck with this as there are no identic Ids to match both values. What I have so far brings no result:
Select
A.Email
B.CouponCode
FROM Emailaddresses as A
JOIN CouponCodes as B
on A.Email = B.CouponCode
A hint would be great as search did not bring me any further yet.
Edit -
Table A (Addresses)
-------------------
Column A | Column B
-------------------------
email1#gmail.com True
email2#gmail.com
email3#gmail.com True
email4#gmail.com
Table B (Voucher)
-------------------
ABCD1234
ABCD5678
ABCD9876
ABCD5432
Table C
-------------------------
column A | column B
-------------------------
email1#gmail.com ABCD1234
email2#gmail.com ABCD5678
email3#gmail.com ABCD9876
email4#gmail.com ABCD5432
Sample Data:
While joining without proper keys is not a good solution, for your case you can try this. (note: not tested, just a quick suggestion)
;with cte_email as (
select row_number() over (order by Email) as rownum, Email
from Emailaddresses
)
;with cte_coupon as (
select row_number() over (order by CouponCode) as rownum, CouponCode
from CouponCodes
)
select a.Email,b.CouponCode
from cte_email a
join cte_coupon b
on a.rownum = b.rownum
You want to randomly join records, one email with one coupon each. So create random row numbers and join on these:
select
e.email,
c.couponcode
from (select t.*, row_number() over (order by newid()) as rn from emailaddresses t) e
join (select t.*, row_number() over (order by newid()) as rn from CouponCodes t) c
on c.rn = e.rn;
Give a row number for both the tables and join it with row number.
Query
;with cte as(
select [rn] = row_number() over(
order by [Column_A]
), *
from [Table_A]
),
cte2 as(
select [rn] = row_number() over(
order by [Column_A]
), *
from [Table_B]
)
select t1.[Column_A] as [Email_Id], t2.[Column_A] as [Coupon]
from cte t1
join cte2 t2
on t1.rn = t2.rn;
Find a demo here
I am having problems grouping by the month of a date when using a function. It was working before but the query was less complicated as I am now using a function that uses a rolling year from the current month. Here is my code.
SELECT
CASE
WHEN DATEDIFF(mm,dbo.fn_firstofmonth(getdate()), dbo.fn_firstofmonth(D.expected_date)) < 12
THEN DATEDIFF(mm,dbo.fn_firstofmonth(getdate()), dbo.fn_firstofmonth(D.expected_date)) + 1
ELSE 13 END AS [Expected Month],
P.probability AS [Category], COUNT(O.id) AS [Customers]
FROM opportunity_probability P
INNER JOIN opportunity_detail D ON D.probability_id = P.id
INNER JOIN opportunities O ON D.opportunity_id = O.id
INNER JOIN
(
SELECT opportunity_id
FROM opportunity_detail
GROUP BY opportunity_id
) T ON T.opportunity_id = O.customer_id
GROUP BY P.probability, MONTH(D.expected_date)
ORDER BY P.probability, MONTH(D.expected_date)
It works if I have D.expected_date in the GROUP BY but I need to group on the MONTH of this date as it does not bring through the data correctly.
You could always remove the group by, then put your entire select into another select, and than group by the outer select:
select t.A, t.B from (select A, datepart(month, b) as B) t group by t.A, t.B
This way you can address your month field as if it where a normal field.
Example is far from complete, but should get you on your way.
You can try to find month by this code:
GROUP BY P.probability, DATEPART(month, D.expected_date)
try this
SELECT
to_char(D.expected_date, 'YYYY-MM'),
CASE
WHEN DATEDIFF(mm,dbo.fn_firstofmonth(getdate()), dbo.fn_firstofmonth(D.expected_date)) < 12
THEN DATEDIFF(mm,dbo.fn_firstofmonth(getdate()), dbo.fn_firstofmonth(D.expected_date)) + 1
ELSE 13 END AS [Expected Month],
P.probability AS [Category], COUNT(O.id) AS [Customers]
FROM opportunity_probability P
INNER JOIN opportunity_detail D ON D.probability_id = P.id
INNER JOIN opportunities O ON D.opportunity_id = O.id
INNER JOIN
(
SELECT opportunity_id
FROM opportunity_detail
GROUP BY opportunity_id
) T ON T.opportunity_id = O.customer_id
GROUP BY P.probability, to_char(D.expected_date, 'YYYY-MM')
ORDER BY P.probability, to_char(D.expected_date, 'YYYY-MM')