group by SKU with count - sql

I have a table with parts in it:
parts (partID, sku, ....)
The SKU looks like:
ABC1232
ABC1332
DSE234
XYZ322
XYZ332
etc...
I need to group by manufacturer, so I have to get a substring of the SKU, taking the first 3 characters and then grouping them together and getting a count of them.
So the resulting output needs to look like:
MFG COUNT
ABC 2343
DSE 43
XYX 323

SELECT SUBSTRING(sku, 1, 3) AS MFG, count(*) AS COUNT
FROM parts
GROUP BY SUBSTRING(sku, 1, 3)

You can also try
SELECT LEFT(sku, 3) AS MFG, count(*) AS COUNT
FROM parts
GROUP BY LEFT(sku, 3)
Found at LEFT (Transact-SQL)

Related

Is there a way to substitute GROUP BY

I have two tables i'm working with:
comporder(quantity,cod(Fk on cod(product),cod_ship);
product(cod(Pk),price);
I need to produce a query that will give me the sum of the prices of the products that are in the comporder table for each cod_ship;
I came up with this query:
SELECT sum(p.price),c.cod_ship
FROM product as p JOIN comporder as c
ON(p.cod=c.cod)
GROUP BY c.cod_ship;
However I am not allowed to use the GROUP BY function and I can't seem to have the price where the quanity is above one.
For exampe if in my comporder table I have:
quantity cod cod_ship
2 "1234567890" 27
3 "1234567890" 28
2 "7894561230" 28
1 "5678324515" 28
4 "1234567890" 27
1 "1234567890" 27
And if in my product table I have:
cod price
"1234567890" 20.00
"7894561230" 19.99
"5678324515" 25.99
If I apply my query the result will be:
sum cod_ship
60 27
65.979 28
When te actual result should be, based on the quantity of the products in the table comporder:
sum // cod_ship//
140 // 27//
125,97 //28//
So I can't seem to figure out how to get the sum also based on the quantity of the product and witouth the GROUP BY function, I should just show the sum as "output", can somebody help me out understand how can I do it?
REPLYING TO COMMENTS:
I cannot use group by due to an assignment.
I am using PostgreSQL 12.1
As requested by the OP in the comments here is a solution using GROUP BY:
SELECT SUM(price * quantity) as sum, cod_ship FROM comporders
INNER JOIN products ON products.cod = comporders.cod
GROUP BY cod_ship;
Edit:
Here is the solution without GROUP BY:
SELECT DISTINCT
(
SELECT SUM(price * quantity)
FROM products
INNER JOIN comporders ON products.cod = comporders.cod
WHERE cod_ship = results.cod_ship
) AS sum,
cod_ship
FROM comporders AS results;
It works by first selecting a unique list of cod_ship ids (what we previously grouped the query by).
Then we execute a subquery using the cod_ship id to calculate the sum for each column. We use the table alias results in order to reference the values in the parent query of the subquery.
SQL Fiddle Link
You can do aggregation in subselect like this:
SELECT (
SELECT SUM(p.price)
FROM product AS p
WHERE p.cod = c.cod
) AS price, c.cod_ship
FROM comporder AS c

Sum rows with same identification-number and sort by custom order

I have the following table structure for the table "products":
id amount number
1 10 M6545
2 32 M6424
3 32 M6545
4 49 M6412
... ... ...
I want to select the sum of amounts of all rows with the same number. The rows with the same number should be summed up to one sum. That means:
M6545 -> Sum 42
M6424 -> Sum 32
M6421 -> Sum 49
My query looks like the following and still does not work:
SELECT SUM(amount) as SumAm FROM products WHERE number IN ('M6412', 'M6545')
I want to find a way where I can only select the sum ordered by the numbers in the "IN" statement. That means, the result table should look like:
SumAm
49
42
The sums should not be ordered in some way. It should match the order of numbers in the IN clause.
use group by number
SELECT number, SUM(amount) as SumAm FROM products
--WHERE number IN ('M6412', 'M6545') i think you dont need where clause
group by number
But if you want just for 'M6412', 'M6545' then you need where clause that you showed in your 2nd output sample
Use group by and aggregation
SELECT SUM(amount) as SumAm FROM products
WHERE number IN ('M6412', 'M6545')
group by number
You can't order by results based directly on the order of the IN clause.
What you can do is something like this:
SELECT SUM(amount) as SumAm
FROM products
WHERE number IN ('M6412', 'M6545')
GROUP BY number -- You must group by to get a row for each number
ORDER BY CASE number
WHEN 'M6412' THEN 1
WHEN 'M6545' THEN 2
END
Of course, the more items you have in your IN clause the more cumbersome this query will get. Therefor another solution might be more practical - joining to a table variable instead of using IN:
DECLARE #Numbers AS TABLE
(
sort int identity(1,1), -- this will hold the order of the inserted values
number varchar(10) PRIMARY KEY -- enforce unique values
);
INSERT INTO #Numbers (number) VALUES
('M6412'),
('M6545')
SELECT SUM(amount) as SumAm
FROM products As p
JOIN numbers As n ON p.Number = n.Number
-- number and sort have a 1 - 1 relationship,
-- so it's safe to group by it instead of by number
GROUP BY n.sort
ORDER BY n.sort
Your requirement is non-sense... this is not how IN is designed to work. Having said that, the following will give you the result in the desired order:
SELECT SUM(amount)
FROM (VALUES
('M6545', 1),
('M6412', 2)
) AS va(number, sortorder)
INNER JOIN sumam ON va.number = sumam.number
GROUP BY va.number, va.sortorder
ORDER BY va.sortorder
It is somewhat better than writing a CASE statement when you would need to add a WHEN condition for each number.

Using Count case

So I've been just re-familiarizing myself with SQL after some time away from it, and I am using Mode Analytics sample Data warehouse, where they have a dataset for SF police calls in 2014.
For reference, it's set up as this:
incident_num, category, descript, day_of_week, date, time, pd_district, Resolution, address, ID
What I am trying to do is figure out the total number of incidents for a category, and a new column of all the people who have been arrested. Ideally looking something like this
Category, Total_Incidents, Arrested
-------------------------------------
Battery 10 4
Murder 200 5
Something like that..
So far I've been trying this out:
SELECT category, COUNT (Resolution) AS Total_Incidents, (
Select COUNT (resolution)
from tutorial.sf_crime_incidents_2014_01
where Resolution like '%ARREST%') AS Arrested
from tutorial.sf_crime_incidents_2014_01
group by 1
order by 2 desc
That returns the total amount of incidents correctly, but for the Arrested, it keeps printing out 9014 Arrest
Any idea what I am doing wrong?
The subquery is not correlated. It just selects the count of all rows. Add a condition, that checks for the category to be equal to that of the outer query.
SELECT o.category,
count(o.resolution) total_incidents,
(SELECT count(i.resolution)
FROM tutorial.sf_crime_incidents_2014_01 i
WHERE i.resolution LIKE '%ARREST%'
AND i.category = o.category) arrested
FROM tutorial.sf_crime_incidents_2014_01 o
GROUP BY 1
You could use this:
SELECT category,
COUNT(Resolution) AS Total_Incidents,
SUM(CASE WHEN Resolution LIKE '%ARREST%' THEN 1 END) AS Arrested
FROM tutorial.sf_crime_incidents_2014_01
GROUP BY category
ORDER BY 2 DESC;

If there is only 1 quantity, display the name, not the number

Imagine it like a student quiz.
10 Students get a C.
6 Students get a B.
1 Student gets an A.
Rather than showing that 1 student got an A, is there a way to show the name of the student that got that result?
This is part of the result set I get. The 2 letters represent the 2 first letters of a 6 letter string corresponding to a shelf and its warehouse. If the quantity (value on the right) is 1, I want to display the full shelf value.
I am currently using a SUBSTRING to get the 2 letters and a COUNT to get the quantity
The query I am using so far may seem complicated but here it is
SELECT DISTINCT SUBSTRING(location, 1, 2) AS ShelfNum,
COUNT(location) as Quantity
FROM warehouse_locations
WHERE unitId_unitId = 1
GROUP BY SUBSTRING(location, 1, 2)
ORDER BY ShelfNum asc
If I try to add the full location on the end if the quantity is 1, I get a group-by error
You can use a case expression to choose between max(name) and count(location) based on the result. You will need to convert the count(location) to the datatype that is returned by max(name).
Sql Server example:
select
substring(location, 1, 2) as ShelfNum
, case when count(location) = 1 then max(name)
else cast(count(location) as varchar(32))
end as Quantity
from warehouse_locations
where unitId_unitId = 1
group by substring(location, 1, 2)
order by ShelfNum asc
Also: you do not need to use distinct when you are using group by.
This would work.
SELECT CASE WHEN Quantity = 1
THEN location
ELSE ShelfNum END as ShelfNum
,Quantity
FROM (
SELECT DISTINCT SUBSTRING(location, 1, 2) AS ShelfNum,
location,
COUNT(location) as Quantity
FROM warehouse_locations
WHERE unitId_unitId = 1
GROUP BY SUBSTRING(location, 1, 2), location
)
ORDER BY ShelfNum asc

Sum the Count Visits - Sql

I came across a scenario and I am confused on how I can get it to work.
How can I SUM two different groups from the COUNT result?
Select Count(VisitID), Types
From Customers
Group by Types;
Result gets to be like:
Type VisitID
A 10
B 20
C 1
I want the result to be as follows:
Type VisitID
A+C 11
Thanks.
With a CTE for example:
WITH CustomerCounts ([Count], [Types])
AS
(
Select Count(VisitID), [Types]
from Customers
Group by [Types]
)
Select SUM([Count])
From CustomerCounts
Where [Types] in ('A', 'C')
Try this
Select only type you want then use pivot to convert row to column then sum column like this SELECT pv.[a] + pv.[c] from (..........)