Order sql results using a Count() value from another table - sql

assuming we have a users table like this:
ID | USERNAME | STATUS |
01 | Aname | 1 |
02 | Bname | 1 |
03 | Cname | 2 |
04 | Dname | 1 |
there are also two other tables, where, for each user, records the items that the users "has" for istance, video and photos, lets assume the video table is like this:
ID | USER | VIDEO |
01 | 01 | aaaa |
02 | 01 | bbbb |
03 | 02 | cccc |
04 | 02 | dddd |
05 | 03 | eeee |
06 | 03 | ffff |
07 | 03 | gggg |
the same for the photos:
ID | USER | PHOTO |
01 | 01 | aaaa |
02 | 02 | cccc |
03 | 02 | dddd |
04 | 03 | eeee |
05 | 03 | ffff |
06 | 03 | gggg |
now, i'm trying to order the results of the first table, on the STATUS field, so the users with status 2 will go at the end (or beginning) of the results, but i would like to order the others by the fact that they have, or have not videos or photos. Actually for all the users in the status 1 I check if they have video AND photos and display a message like "warning, you have no videos" or something, i would like also to order all the users on the status basis AND on the fact that they have or not photos or video... something like:
SELECT id,username,status,NumOfPhotos,NumOfVideos order by status ASC, numOfPhotos ASC, NumOfVideos DESC
where NumOfPhotos, for example is SELECT COUNT(*) FROM PHOTOS WHERE USER = USERS.ID
Is that possible? is that possible in a single statement?

This is an example on SQL Server, but something similar should work well on other RDBMS
SELECT
id, username, status, COALESCE(NumOfPhotos,0) AS NumOfPhotos,COALESCE(NumOfVideos,0) AS NumOfVideos
FROM dbo.Users u
LEFT JOIN (SELECT [USER], COUNT(*) AS NumOfPhotos FROM dbo.Photos GROUP BY [USER]) ph ON ph.[USER] = u.ID
LEFT JOIN (SELECT [USER], COUNT(*) AS NumOfVideos FROM dbo.Videos GROUP BY [USER]) vd ON vd.[USER] = u.ID
ORDER BY status ASC, numOfPhotos ASC, NumOfVideos DESC
SQLFiddle

Related

SELECT Top values for each records

I have been battling through this query/query design for sometime now and I thought it's time to ask the experts! Here's my table results:
ID | Status | date |
---------------------------------
05 | Returned | 20/6/2018 |
03 | Sent | 12/5/2018 |
01 | Pending | 07/6/2018 |
01 | Engaged | 11/4/2018 |
03 | Contacted | 16/4/2018 |
05 | Surveyed | 04/3/2017 |
05 | No Contact | 05/3/2017 |
How do I get it to return top/newest value for each ID:
ID | Status | date |
---------------------------------
05 | Returned | 20/6/2018 |
03 | Sent | 12/5/2018 |
01 | Pending | 07/6/2018 |
I've tried group by, TOP 1, Distinct and results still not what I wanted. Also, displaying the results by top 5% is won't do either as the ID can be more than just 3 types.
My QUERY below:
INSERT INTO TmpAllcomsEmployee ( StatusID, EmployeeID, CommunicationDate )
SELECT DISTINCT CommunicationLog.StatusID, TmpAllcomsEmployee.EmployeeID,
Max(CommunicationLog.CommunicationDate) AS MaxOfCommunicationDate
FROM CommunicationLog RIGHT JOIN TmpAllcomsEmployee ON
CommunicationLog.EmployeeID = TmpAllcomsEmployee.EmployeeID
GROUP BY CommunicationLog.StatusID, TmpAllcomsEmployee.EmployeeID
ORDER BY Max(CommunicationLog.CommunicationDate) DESC;
One method is a correlated subquery:
select cl.*
from CommunicationLog as cl
where cl.date = (select max(cl2.date)
from CommunicationLog as cl2
where cl2.EmployeeID = cl.EmployeeID
);
This gets the most recent record for each employee in CommunicationLog. You can join in the other table if you really need it. It does not seem unnecessary unless you are using it for filtering.

SQL Server - Query with Join and mutiple conditions

I'm trying to query four table as below:
Table1: Users
User | Name
-------------
01 | Phil
-------------
02 | John
-------------
03 | Marc
-------------
04 | Rob
Order: Integer and Incremental / Name: varchar
Table2: Status
Status | Description
--------------------
01 | Canceled
--------------------
02 | Confirmed
--------------------
03 | Bulding
--------------------
.. | .....
--------------------
15 | Finished
Status: Integer and Incremental / Description: varchar
Table3: Build
Order | Date | Place
----------------------------
01 | 01/01/2014 | MG
----------------------------
02 | 02/02/2014 | SP
----------------------------
05 | 03/03/2014 | BA
Order: Integer / Date: Date / Place: Varchar
Table4: Orders
Order | User | Status
-----------------------
01 | 02 | 01
-----------------------
02 | 01 | 11
-----------------------
03 | 03 | 15
-----------------------
04 | 01 | 03
-----------------------
05 | 04 | 02
Order: Integer and Incremental / User: Integer / Status: Integer
I have to query Table 4 to show all orders (except status 1,15) join with table 01, table 02 and table 03 ordering by date at table 03. The problem is table 03 not always have a row with the order number and the this order doesn't show at query.
I need a result like this:
Query Result:
Order | User | Name | Status | Description | Date | Place
----------------------------------------------------------------
02 | 01 | Phil | 11 | Painting | 02/02/2014 | SP
----------------------------------------------------------------
05 | 04 | Rob | 02 | Confirmed | 03/03/2014 | BA
----------------------------------------------------------------
04 | 01 | Phil | 03 | Bulding | |
Thanks for the help !!!
Use "LEFT OUTER JOIN" for table 3. That will return all the records in the other tables, the matches in table 3, and if table 3 doesn't match, it will show up blank.
For example:
SELECT *
FROM Orders
LEFT OUTER JOIN Build ON Order.Order = Build.Order
This will return all of the results for Orders and the matches from Build. Note, the table you want to keep all the records from must go on the LEFT side of the ON statement (ON Order.Order = Build.Order).
More info: http://technet.microsoft.com/en-us/library/ms187518%28v=SQL.105%29.aspx

Sum of count from external table

I need to search for the sum of the games made by specific developers. I have two tables:
_____________________________
|____________GAMES____________|
| Id | Title | id_dev | hits |
| 01 | abc | 1 | 20 |
| 02 | xyz | 2 | 15 |
| 03 | cde | 1 | 9 |
_______________
|__DEVELOPERS___|
| Id | Title |
| 01 | poi |
| 02 | asd |
| 03 | qwe |
I want result formatted like Developers title 40, where 40 is the sum of all hits of the games with the ID of this developer. How can I go about this?
SELECT developers.title, COUNT(count) AS total FROM (SELECT COUNT(games.hits) AS count
FROM games
GROUP BY id_dev
HAVING count > 1) as A
FROM developers
JOIN games
WHERE developers.id = games.id_dev
This is a simple join and aggregate, so you are overcomplicating things:
select d.id, d.title, sum(g.hits)
from games g join
developers d
on g.id_dev = d.id
group by d.id, d.title;

Count number of records with matching values in separate fields

I have a table (myTable) as such:
id | name | orig_id
----+-------+--------
01 | Bill | -
02 | Tom | 01
03 | Sam | 01
04 | Alex | 02
05 | Phil | -
06 | Bob | 01
I'd like a query that returns each record but with an added column containing the count of other rows that have an orig_id equal to the current row's id.
The resulting table would look like this:
id | name | orig_id | mycount
----+-------+---------+--------
01 | Bill | - | 3
02 | Tom | 01 | 1
03 | Sam | 01 | 0
04 | Alex | 02 | 0
05 | Phil | - | 0
06 | Bob | 01 | 0
I've tried the following query, but get no results:
SELECT *, COUNT(t.name) AS mycount
FROM "myTable" AS t
WHERE t.id=t.orig_id
GROUP BY t.id;
How can I achieve the desired results?
You can do this with a join and aggregation:
SELECT t.*, tsum.mycount
FROM myTable t join
(select orig_id, count(name) as mycount
from myTable
group by orig_id
) tsum
on t.id = tsum.orig_id;
A simple left join with count will do it:
select t.id, t.name, t.orig_id, count(o.id) mycount
from myTable t
left join myTable o on t.id = o.orig_id
group by t.id, t.name, t.orig_id
See a live demo on SQLFiddle that produces this result:
ID NAME ORIG_ID MYCOUNTÂ
01 Bill (null) 3
02 Tom 01 1
03 Sam 01 0
04 Alex 02 0
05 Phil (null) 0
06 Bob 01 0

SQL, select in tables

Hey I don't know how to do it....
Its a homework: List the code and the consumers who bought cars only 'Argentina' country.
Table sell:
customer | resell | veicle | date | value
---------+---------+-----------+------------+----------
02 | 01 | 03 | 2010-02-05 | 17500.00
04 | 02 | 01 | 2010-01-07 | 28000.00
01 | 03 | 08 | 2010-02-15 | 28000.00
02 | 03 | 02 | 2010-03-12 | 42000.00
03 | 04 | 06 | 2010-02-06 | 11500.00
03 | 02 | 05 | 2010-01-25 | 22100.00
01 | 01 | 04 | 2010-01-21 | 15500.00
Table customer:
cod | name | lastname
--------+------------+------------
01 | Jose | Alves
02 | Paulo | Cunha
03 | Maria | DPaula
04 | Joana | Silveria
Table veicle:
cod |manufacturer| model | year | country | price
--------+------------+-----------------+------+-----------+----------
01 | 01 | Gol | 2000 | Brasil | 25000.00
02 | 01 | Golf | 2005 | Argentina | 39000.00
03 | 04 | Ford Ka | 1990 | Brasil | 15000.00
04 | 03 | Corsa Seda | 1995 | Brasil | 12500.00
05 | 04 | Fiesta | 2003 | Argentina | 20000.00
06 | 03 | Corsa Seda | 1995 | Argentina | 10000.00
07 | 05 | Palio | 2002 | Brasil | 15000.00
08 | 05 | Siena | 2006 | Brasil | 26000.00
I guess it to start:
SELECT customer.cod, customer.name
FROM sell, customer
WHERE (SELECT cod
FROM veicle
WHERE veicle.country = 'Argentina') = sell.veicle;
To select only the argentine cars...
Please guide-me to the answer.
SELECT c.*
FROM customer c
WHERE EXISTS (
SELECT 1
FROM sell s
JOIN veicle v ON v.cod = s.veicle
WHERE s.customer = c.cod
AND v.country = 'Argentina'
)
AND NOT EXISTS (
SELECT 1
FROM ...
);
I'll leave the rest for you, as this is homework. Fill in for ... to exclude customers that have bought vehicles that are not from Argentina - very similar to the first EXISTS clause. If you have understood the first, you can complete the rest.
Try this
SELECT DISTINCT customer.cod, customer.name || customer.lastname FROM customer, veicle, sell WHERE customer.cod = sell.customer AND veicle.cod = sell.veicle AND veicle.country = 'Argentina'
Look into table joins. That way instead of doing a subquery (what is in your where statement) you can instead join on the tables (kindof like your From clause but you should specify what it joins on) and then in your where you can just put veicle.country = 'Argentina'.
And FYI veicle is spelled wrong. It should be vehicle.
Try this :
SELECT c.cod, c.name,c.last_name,v.model
FROM sell as s JOIN customer as c JOIN veicle as v ON s.veicle = v.cod and s.customer = c.cod
WHERE v.country = 'Argentina'
WITH minima AS (
SELECT DISTINCT s.customer
, MIN(v.country) AS mi
, MAX(v.country) AS ma
FROM sell s
JOIN veicle v ON s.resell = v.cod
GROUP BY s.customer
)
SELECT cu.* FROM customer cu
JOIN minima mm ON mm.customer = cu.cod
WHERE mm.mi = 'Argentina'
AND mm.ma = 'Argentina'
;