What can I use other than Group By? - sql

I have a question that uses this DML statement
SELECT SupplierID, COUNT(*) AS TotalProducts
FROM Products
GROUP BY SupplierID;
I'm trying to get the same results without using "Group By". I can use a table variable or a temp table, with Insert and Update if needed. Also, using While and IF-Else is allowed.
I'm really lost any help would be awesome. Thanks SO Community.
This is used in SQL Server. Thanks again.

You can always use SELECT DISTINCT with window functions:
SELECT DISTINCT SupplierID,
COUNT(*) OVER (PARTITION BY SupplierId) AS TotalProducts
FROM Products;
But GROUP BY is the right way to write an aggregation query.

You may also use the following query :
select distinct P.SupplierID, (select count(*) from Products
where SupplierID=P.SupplierID) TotalProducts from Products P
You will get the same result using the above query, but i don't think avoiding GROUP BY is a good idea!

Using a subquery:
SELECT DISTINCT SupplierID
,(SELECT COUNT(*)
FROM Products P2
WHERE P2.SupplierID = P.SupplierID
) AS TotalProducts
FROM Products P
The distinct is to remove duplicates... the count executes for every row so without distinct you would get repeat answers for supplierID.

Another way
select distinct supplierId, p2.ttl
from products p1
cross apply
(
select count(*)
from products p2
where p1.supplierId = p2.supplierId
) p2(ttl);

Related

sql select with group by and join for lookup

Imagine I have a product table and an orders table. I want to list out the most recent order for each product
I imagine something like this
select name, description, price, max(date)
from product
join order on order.item = product.name
group by order.item
But my postgres DB complains that I cant have raw fields (sqlite doesnt complain) I need to have aggregate function. I can put min() for each column but that seems like a waste, given that all the values for a particular product are always the same. I wondered about 'distinct' but that doesnt seem to help here
NOTE - I need standard portable SQL , not specific to any given engine.
In Postgres, you can use distinct on:
select distinct on (o.item) p.name, description, price, date
from product p join
order o
on o.item = p.name
order by o.item, date desc;
I added aliases into the query. I strongly advise you to always qualify all column names. I would do that but I don't know where they come from in most cases.
If you require standard ANSI SQL you can use a window function:
select *
from (
select p.name, p.description, p.price,
o.date,
max(o.date) over (partition by o.item) as last_date
from product p
join "order" o on o.item = p.name
) t
where date = last_date;
But in Postgres distinct on () is usually a lot faster.
If it was Oracle or MS you would need to group by all the fields in your select that aren't aggregate functions.
It would be an extra line before "order by" with "group by p.name, description, price, date" ...
About Postgres I am not so sure, but probably it will work.
You can use correlated subquery :
select p.name, p.description, p.price, o.date
from product p inner join
order o
on o.item = p.name
where o.date = (select max(o1.date)
from order o1
where o1.item = p.name
);

Can we use order by in subquery? If not why sometime could use top(n) order by?

I'm an entry level trying to learn more about SQL,
I have a question "can we use order by in subquery?" I did look for some article says no we could not use.
But on the other hand, I saw examples using top(n) with order by in subquery:
select c.CustomerId,
c.OrderId
from CustomerOrder c
inner join (
select top 2
with TIES CustomerId,
COUNT(distinct OrderId) as Count
from CustomerOrder
group by CustomerId
order by Count desc
) b on c.CustomerId = b.CustomerId
So now I'm bit confused.
Could anyone advise?
Thank you very much.
Yes, you are right we cannot use order by in a inner query. Because it is acting as a table. A table in itself needs to be sorted when queried for different purposes.
In your query itself the inner query is select some records using Top 2. Eventhough these are top 2 records only, they form a table with 2 records which is enough for it to recognized as a table and join it with another table
The right query will be:-
SELECT * FROM
(
SELECT c.CustomerId, c.OrderId, DENSE_RANK() OVER(ORDER BY b.count DESC) AS RANK
FROM CustomerOrder c
INNER JOIN
(SELECT CustomerId, COUNT(distinct OrderId) as Count
FROM CustomerOrder GROUP BY CustomerId) b
ON c.CustomerId = b.CustomerId
) a
WHERE RANK IN (1,2);
Hope I have answered your question.
Yes we can use order by clause in sub query, for example i have a table named as product (check the screen shot of table http://prntscr.com/f15j3z). Chek this query on your side and revert me in case of any doubt.
select p1.* from product as p1 where product_id = (select p2.product_id from product as p2 order by product_id limit 0,1)
yes we can use order by in subquery,but it is pointless to use it.
It is better to use it in the outer query.There is no use of ordering the result of subquery, because result of inner query will become the input for outer query and it does not have to do any thing with the order of the result of subquery.

Does this query use any sub-queries or temporary tables? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
How can I rewrite this query without sub-queries?
I am not allowed to use sub-queries or any kind of temporary tables as a part of an answer, does this query use any of those?
SELECT DISTINCT item_no, avg_price
FROM Prices
NATURAL JOIN (SELECT AVG(totalamount) avg_price FROM Prices GROUP BY price) av
WHERE sum > aurnover ORDER BY avg_price DESC , branch;
You are using two sub-queries on these lines:
NATURAL JOIN (SELECT branch, AVG(totalamount) avg_price FROM Prices GROUP BY branch) av
NATURAL JOIN (SELECT item_no,branch, SUM(totalamount) sum FROM Prices GROUP BY branch, table_no) su
Well, you've definitely got subqueries (you can see that clearly with the nested SELECT calls).
You'd likely need to inspect the output of EXPLAIN-ing that (just append EXPLAIN to the start of that query for your database) to know for sure if it'll generate a temporary table. Look for the text "using temporary" in the "Extra" column.
What you have are derived tables.
A derived table is similar to selecting from a view
Consider this:
SELECT
*
FROM (SELECT * FROM TABLEA) A
If you made a the table you are selecting from the outside is derived from the inner select
Note as a derived table the select will only run once
This is an example of a sub query which will run once for every tableA Record
Select
(Select ID from TABLEB WHERE tableB.Code = TableA.Code) AS TableBID
FROM TableA
This is also a subquery
Select
*
FROM TableA
Where TableA.Code IN (Select TABLEB.Code From TableB)
Subquerys are generally used in Where Clauses and Columns but can cause serious preformance issues.

SQL Server: Retrieve the duplicate value in a column

How could I filter out the duplicate value in a column with SQL syntax?
Thanks.
A common question, though filtering out suggests you want to ignore the duplicate ones? If so, listing unique values:
SELECT col
FROM table
GROUP BY col
HAVING (COUNT(col) =1 )
If you just want to filter so you are left with the duplicates
SELECT col, COUNT(col) AS dup_count
FROM table
GROUP BY col
HAVING (COUNT(col) > 1)
Used www.mximize.com/how-to-find-duplicate-values-in-a-table- as a base in 2009; website content has now gone (2014).
Use DISTINCT or GROUP BY** clause.
Select DISTINCT City from TableName
OR
Select City from TableName GROUP BY City
Depending on how you mean "filter" you could either use DISTINCT or maybe GROUP BY both are used to Remove or Group duplicate entries.
Check the links for more information.
A snippet from the DISTINCT-link above:
SELECT DISTINCT od.productid
FROM [order details] OD
SELECT od.productid
FROM [order details] OD
GROUP BY od.productid
Both of these generally result in the same output.
You asked for a list of the duplicates. Here is a simple way using the except operator (SQL 2008 +).
select [column] from Table1
except
select distinct [column] from Table1;
Alternatively, you could use standard SQL
select [column] from Table1
where [column} not in
(select distinct [column} from Table1);
distinct would be the keyword to filter douplicates.
May be you can explain a little more what you're trying to achieve ?

How to reference a custom field in SQL

I am using mssql and am having trouble using a subquery. The real query is quite complicated, but it has the same structure as this:
select
customerName,
customerId,
(
select count(*)
from Purchases
where Purchases.customerId=customerData.customerId
) as numberTransactions
from customerData
And what I want to do is order the table by the number of transactions, but when I use
order by numberTransactions
It tells me there is no such field. Is it possible to do this? Should I be using some sort of special keyword, such as this, or self?
use the field number, in this case:
order by 3
Sometimes you have to wrestle with SQL's syntax (expected scope of clauses)
SELECT *
FROM
(
select
customerName,
customerId,
(
select count(*)
from Purchases
where Purchases.customerId=customerData.customerId
) as numberTransactions
from customerData
) as sub
order by sub.numberTransactions
Also, a solution using JOIN is correct. Look at the query plan, SQL Server should give identical plans for both solutions.
Do an inner join. It's much easier and more readable.
select
customerName,
customerID,
count(*) as numberTransactions
from
customerdata c inner join purchases p on c.customerID = p.customerID
group by customerName,customerID
order by numberTransactions
EDIT: Hey Nathan,
You realize you can inner join this whole table as a sub right?
Select T.*, T2.*
From T inner join
(select
customerName,
customerID,
count(*) as numberTransactions
from
customerdata c inner join purchases p on c.customerID = p.customerID
group by customerName,customerID
) T2 on T.CustomerID = T2.CustomerID
order by T2.numberTransactions
Or if that's no good you can construct your queries using temporary tables (#T1 etc)
There are better ways to get your result but just from your example query this will work on SQL2000 or better.
If you wrap your alias in single ticks 'numberTransactions' and then call ORDER BY 'numberTransactions'
select
customerName,
customerId,
(
select count(*)
from Purchases
where Purchases.customerId=customerData.customerId
) as 'numberTransactions'
from customerData
ORDER BY 'numberTransactions'
The same thing could be achieved by using GROUP BY and a JOIN, and you'll be rid of the subquery. This might be faster too.
I think you can do this in SQL2005, but not SQL2000.
You need to duplicate your logic. SQL Server isn't very smart at columns that you've named but aren't part of the dataset in your FROM statement.
So use
select
customerName,
customerId,
(
select count(*)
from Purchases p
where p.customerId = c.customerId
) as numberTransactions
from customerData c
order by (select count(*) from purchases p where p.customerID = c.customerid)
Also, use aliases, they make your code easier to read and maintain. ;)