How to get a correlated subquery as column - sql

I dont know how I can do this sql query, probably its simple but I don't know how i can do it.
I have 2 tables:
Table_Articles:
COD NAME
1 Bottle
2 Car
3 Phone
Table_Articles_Registered
COD_ARTICLE DATE
1 05/11/2014
1 06/11/2014
1 07/11/2014
2 08/11/2014
2 09/11/2014
3 05/11/2014
I want take in the table Table_Articles_Registered the row with the MAX date , finally I want get this result:
COD NAME DATE
1 Bottle 07/11/2014
2 Car 09/11/2014
3 Phone 05/11/2014
I need use the sencente like this. The problem its in the subquery. Later I use other inner join in the sentence, this is only a fragment.
select
_Article.Code,
_Article.Description ,
from Tbl_Articles as _Article left join
(
select top 1 *
from ArticlesRegisterds where DATE_REGISTERED <= '18/11/2014'
order by DATE_REGISTERED
)
as regAux
on regAux.CODE_ARTICLE= _Article.CODE
I dont know how can I connect the field CODE_ARTICLE in the table ArticlesRegisterds with the first query.

I think this is a basic aggregation query with a join:
select a.cod, a.name, max(ar.date) as date
from Artiles a join
ArticlesRegisterds ar
on ar.cod_article = a.cod
group by a.cod, a.name

Try this:-
SELECT TAR.COD_ARTICLE, TA.NAME, MAX(TAR.DATE)
FROM Table_Articles_Registered TAR JOIN
Table_Articles.TA ON TAR.COD_ARTICLE = TA.COD
GROUP BY TAR.COD_ARTICLE, TA.NAME;

Can't you just do this?:
SELECT
Table_Articles.COD,
Table_Articles.NAME,
(
SELECT MAX(Table_Articles_Registered.DATE)
FROM Table_Articles_Registered
WHERE Table_Articles.COD_ARTICLE=Table_Articles.COD
) AS DATE
FROM
Table_Articles

Related

Postgres, groupBy and count for table and relations at the same time

I have a table called 'users' that has the following structure:
id (PK)
campaign_id
createdAt
1
123
2022-07-14T10:30:01.967Z
2
1234
2022-07-14T10:30:01.967Z
3
123
2022-07-14T10:30:01.967Z
4
123
2022-07-14T10:30:01.967Z
At the same time I have a table that tracks clicks per user:
id (PK)
user_id(FK)
createdAt
1
1
2022-07-14T10:30:01.967Z
2
2
2022-07-14T10:30:01.967Z
3
2
2022-07-14T10:30:01.967Z
4
2
2022-07-14T10:30:01.967Z
Both of these table are up to millions of records... I need the most efficient query to group the data per campaign_id.
The result I am looking for would look like this:
campaign_id
total_users
total_clicks
123
3
1
1234
1
3
I unfortunately have no idea how to achieve this while minding performance and most important of it all I need to use WHERE or HAVING to limit the query in a certain time range by createdAt
Note, PostgreSQL is not my forte, nor is SQL. But, I'm learning spending some time on your question. Have a go with INNER JOIN after two seperate SELECT() statements:
SELECT * FROM
(
SELECT campaign_id, COUNT (t1."id(PK)") total_users FROM t1 GROUP BY campaign_id
) tbl1
INNER JOIN
(
SELECT campaign_id, COUNT (t2."user_id(FK)") total_clicks FROM t2 INNER JOIN t1 ON t1."id(PK)" = t2."user_id(FK)" GROUP BY campaign_id
) tbl2
USING(campaign_id)
See an online fiddle. I believe this is now also ready for a WHERE clause in both SELECT statements to filter by "createdAt". I'm pretty sure someone else will come up with something better.
Good luck.
Hope this will help you.
select u.campaign_id,
count(distinct u.id) users_count,
count(c.user_id) clicks_count
from
users u left join clicks c on u.id=c.user_id
group by 1;
See here query output

Sql Query: How to Base on the row name to display

I have the table data as listed on below:
name | score
andy | 1
leon | 2
aaron | 3
I want to list out as below, even no jacky's data, but list his name and score set to 0
aaron 3
andy 2
jacky 0
leon 2
You didn't specify your DBMS, but the following is 100% standard ANSI SQL:
select v.name, coalesce(t.score, 0) as score
from (
values ('andy'),('leon'),('aaron'),('jacky')
) as v(name)
left join your_table t on t.name = v.name;
The values clause builds up a "virtual table" that contains the names you are interested in. Then this is used in a left join so that all names from the virtual table are returned plus the existing scores from your (unnamed table). For non-existing scores, NULL is returned which is turned to 0 using coalesce()
If you only want to specify the missing names, you can use a UNION in the virtual table:
select v.name, coalesce(t.score, 0) as score
from (
select t1.name
from your_table t1
union
select *
from ( values ('jacky')) as x
) as v(name)
left join your_table t on t.name = v.name;
fixed the query, could list out the data, but still missing jacky, only could list out as shown on below, the DBMS. In SQL is SQL2008.
data
name score scoredate
andy 1 2021-08-10 01:23:16
leon 2 2021-08-10 03:25:16
aaron 3 2021-08-10 06:25:16
andy 4 2021-08-10 11:25:16
leon 5 2021-08-10 13:25:16
result set
name | score
aaron | 1
andy | 5
leon | 7
select v.name as Name,
coalesce(sum(t.score),0) as Score
from (
values ('aaron'), ('andy'), ('jacky'), ('leon')
) as v(name)
left join Score t on t.name=v.name
where scoredate>='2021-08-10 00:00:00'
and scoredate<='2021-08-10 23:59:59'
group by v.name
order by v.name asc
Your question lacks a bunch of information, such as where "Jacky"s name comes from. If you have a list of names that you know are not in the table, just use union all:
select name, score
from t
union all
select 'Jacky', 0;

How to get dates based on months that appear more than once?

I'm trying to get months of Employees' birthdays that are found in at least 2 rows
I've tried to unite birthday information table with itself supposing that I could iterate through them abd get months that appear multiple times
There's the question: how to get birthdays with months that repeat more than once?
SELECT DISTINCT e.EmployeeID, e.City, e.BirthDate
FROM Employees e
GROUP BY e.BirthDate, e.City, e.EmployeeID
HAVING COUNT(MONTH(b.BirthDate))=COUNT(MONTH(e.BirthDate))
UNION
SELECT DISTINCT b.EmployeeID, b.City, b.BirthDate
FROM Employees b
GROUP BY b.EmployeeID, b.BirthDate, b.City
HAVING ...
Given table:
| 1 | City1 | 1972-03-26|
| 2 | City2 | 1979-12-13|
| 3 | City3 | 1974-12-16|
| 4 | City3 | 1979-09-11|
Expected result :
| 2 | City2 |1979-12-13|
| 3 | City3 |1974-12-16|
Think of it in steps.
First, we'll find the months that have more than one birthday in them. That's the sub-query, below, which I'm aliasing as i for "inner query". (Substitute MONTH(i.Birthdate) into the SELECT list for the 1 if you want to see which months qualify.)
Then, in the outer query (o), you want all the fields, so I'm cheating and using SELECT *. Theoretically, a WHERE IN would work here, but IN can have unfortunate side effects if a NULL comes back, so I never use it. Instead, there's a correlated sub=query; which is to say we look for any results where the month from the outer query is equal to the months that make the cut in the inner (correlated sub-) query.
When using a correlated sub-query in the WHERE clause, the SELECT list doesn't matter. You could put 1/0 and it won't throw an error. But I always use SELECT 1 to show that the inner query isn't actually returning any results to the outer query. It's just there to look for, well, the correlation between the two data sets.
SELECT
*
FROM
#table AS o
WHERE
EXISTS
(
SELECT
1
FROM
#table AS i
WHERE
MONTH(i.Birthdate) = MONTH(o.Birthdate)
GROUP BY
MONTH(i.Birthdate)
HAVING
COUNT(*) > 1
);
Seems to be an odd requirement.
This might help with some tweaks. Works in Oracle.
SELECT DATE FROM TABLE WHERE EXTRACT(MONTH FROM DATE)=EXTRACT(MONTH FROM SOMEDATE);
Give this a try and you may be able to dispense with your UNION:
SELECT
EmployeeId
, City
, BirthDate
FROM Employees
GROUP BY
EmployeeId
, City
, BirthDate
HAVING COUNT(Month(BirthDate)) > 2
Here is another approach using GROUP_CONCAT. It's not exactly what you're looking for but it might do the job. Eric's approach is better though. (Note: This is for MySQL)
SELECT GROUP_CONCAT(EmployeeID) EmployeeID, BirthDate, COUNT(*) DupeCount
FROM Employees
GROUP BY MONTH(BirthDate)
HAVING DupeCount> 1;

SQL count involving multiple tables

I have two tables.University and UniversityType.Structure looks like this.
For University
universityId universityName universityTypeId universityTypeName
1 xyz 1 UGC
2 abc 1 UGC
3 lmn 2 NCT
4 pqr 3 AICT
For UniversityType
universityTypeId universityTypeName
1 UGC
2 NCT
3 AICT
The UniversityType table is fixed.Now I want to get the count of universityType that is UGC=2, AICT=1, NCT=1.Now I am writing something like this
SELECT universityId,universityTypeId,universityName FROM
University where universityTypeId=:universityTypeId";
But I am not getting correct result.Can anyone tell.I am new to SQL.
SELECT universityTypeId, COUNT(1)
FROM University where universityTypeId=:universityTypeId
OR
SELECT universityTypeId, COUNT(1)
FROM University
GROUP BY universityTypeId
OR
SELECT universityTypeId, (SELECT COUNT(1)
FROM University where universityTypeId = UniversityType.universityTypeId)
FROM UniversityType
Like this
SELECT universityId,universityName,count(universityTypeId) as total FROM
University group by universityId,universityName
You must add all columns list in the group by clause unless it used in the aggregate function
select universityTypeName, COUNT(University.universityId) FROM UniversityType JOIN University ON UniversityType.universityTypeId = University.universityTypeId GROUP BY UniversityType.universityTypeName
Try this query
You need to join the tables by UniversityType.universityTypeId and count the Universitys. So, try this:
SELECT t.universityTypeName, count(u.universityId) as total
FROM University u, UniversityType t
WHERE u.universityTypeId = t.universityTypeId
GROUP BY u.universityTypeName;
The output it gives is:
UGC|2
NCT|1
AICT|1

MySql Join with Sum

I have a table called RESULTS with this structure :
resultid,winner,type
And a table called TICKETS with this structure :
resultid,ticketid,bet,sum_won,status
And I want to show each row from table RESULTS and for each result I want to calculate the totalBet and Sum_won using the values from table TICKETS
I tried to make some joins,some sums,but I cant get what I want.
SELECT *,COALESCE(SUM(tickets.bet),0) AS totalbets,
COALESCE(SUM(tickets.sum_won),0) AS totalwins
FROM `results` NATURAL JOIN `tickets`
WHERE tickets.status<>0
GROUP BY resultid
Please give me some advice.
I want to display something like this
RESULT WINNER TOTALBETS TOTALWINS
1 2 431 222
2 3 0 0
3 1 23 0
4 1 324 111
Use:
SELECT r.*,
COALESCE(x.totalbet, 0) AS totalbet,
COALESCE(x.totalwins, 0) AS totalwins
FROM RESULTS r
LEFT JOIN (SELECT t.resultid,
SUM(t.bet) AS totalbet,
SUM(t.sum_won) AS totalwins
FROM TICKETS t
WHERE t.status != 0
GROUP BY t.resultid) x ON x.resultid = r.resultid
I don't care for the NATURAL JOIN syntax, preferring to be explicit about how to JOIN/link tables together.
SELECT *, COALESCE(SUM(tickets.bet),0) AS totalbets,
COALESCE(SUM(tickets.sum_won),0) AS totalwins
FROM `results` NATURAL JOIN `tickets`
WHERE tickets.status<>0
GROUP BY resultid
Try to replace the first * with resultid. If this helps, then add more columns to SELECT and add them to GROUP BY at the same time.