SQL Count element and group on element - sql

I am trying to create a view that counts an element and groups it based on a different element.
My table looks something like this
Source
Material
Destination
1
Src1
A123456
Dest2
2
Src1
A658979
Dest1
3
Src1
B123456
Dest1
4
Src1
B658979
Dest1
5
Src1
C123456
Dest2
Description of what I am trying to archive:
Count the materials that start with "A" as "Count Material A" and start with "B" as "Count Material B" and group by destination.
Based on the table above the result should look something like that:
Count Material A
Count Material B
Destination
1
1
2
Dest1
2
1
0
Dest2
For now I am only able to succesfully create the query for the counting part but I cannot figure out how to base the counting on the destination as well.
NOTE: I think I know how to do it when I "hardcode" the destination in the where-clause but it is expected that there will be more destinations in the future so I am trying to future-proof this solution.
Thanks for the help!

We can use conditional aggregation here:
SELECT
Destination,
COUNT(CASE WHEN Material LIKE 'A%' THEN 1 END) AS [Count Material A],
COUNT(CASE WHEN Material LIKE 'B%' THEN 1 END) AS [Count Material B]
FROM yourTable
WHERE Material LIKE 'A%' OR Material LIKE 'B%'
GROUP BY Destination;

Related

GROUP BY in a temp table

I'm working on a stored procedure and altering a temp table to spit out data depending on a specific condition. This stored procedure is quite complex and has like 40 columns, however for this specific issue I simply need to group the records by the DESCR column. The other 37 columns all have the same value so it shouldn't be an issue but in this case how can I group them by their DESCR and consolidate the LATEFEE and CHG values?
The query essentially looks like this:
SELECT [columns1], [column38], t.descr t.chg, t.lateFee, (t.chg + t.lateFee) as Total
FROM #tmpStatement t
INNER JOIN dbo.Association a ON t.AssocID = a.AssocID
INNER JOIN dbo.Company c ON a.CompanyID = c.CompanyID
GROUP BY
[all columns]
If I remove the t.chg or the t.lateFee columns from the GROUP BY clause then SQL tells me that they are invalid in the SELECT list since they're not included in the GROUP BY, however I still want those values in my table.
Currently this is the outcome of the table:
DESCR CHG LATEFEE TOTAL
=================================
Assessment 1 0 1
Spec 0 2 2
Spec 3 0 3
Assessment 0 5 5
Res 3 0 3
 
What I want the expected result to look like:
DESCR CHG LATEFEE TOTAL
=================================
Assessment 1 5 6
Spec 3 2 5
Res 3 0 3
 
Looking at the sample data, you probably need something as simple as:
select descr, other, sum(chg) as chg, sum(latefee) as latefee, sum(chg) + sum(latefee) as total
from t
group by descr, other

How can I sum a row's value in my table based on a specific type?

My table looks like this. Its a table with an inventory of clothes.
Basically, an user can enter a type of clothe and a quantity.
When he did it, it add a new value in the table with the date of the input.
The type 2 is for shoes and the type 3 for shirts
What I'm trying to do is to sum the quantity based on the type like this :
So I tried this :
SELECT name, type, sum(quantity)
from Clothes
where type="2"
group by name
But it didn't work, it sums all the type of clothes. How can I do ?
Use case expressions to do conditional aggregation:
SELECT name,
SUM(case when type = 3 then quantity else 0 end) shirts,
SUM(case when type = 2 then quantity else 0 end) shoes
from Clothes
group by name
You should group using the type too.
Doing this you'll get a table with 3 columns:
1st one with the name, secondo col with the type and the third with the quantity
SELECT name, type, sum(quantity)
from Clothes
group by name,type
Then you should format as you wish the data
If otherwise you want to get the exact result with a query you should dig more deep and maybe using some 'Case' inside the sum function and put a zero if is not of the selected type:
select name,
sum(case when type = 3 then quantity else 0 end) as Shirts,
sum(case when type = 2 then quantity else 0 end) as Shoes
from Clothes
group by name;
result:
A solution using a PIVOT table will achieve the same result with multi-column aggregation of quantities corresponding to the type column:
SELECT [ProductName], [2] As Shoes, [3] As Clothes
FROM
(SELECT [ProductName], [ProductType], [Quantity] FROM [Inventory_Table])
AS DataSource
PIVOT
(SUM([Quantity]) FOR [ProductType] IN ([2], [3])) AS pvt_table
Note: For the above to work in SQL Server T-SQL I had to replace the [Name] and [Type] columns with other columns names.

How to order by document chapter

I need to create stored procedure for getting all the document titles from table, BUT it has to be ordered in a way that shows document chapters FIRST. I really don't know how to do this myself.
It would have to be ordered like this:
ID Chapter Description
1 0001-0299 Title
2 0001-0019 Title
3 0001 "some text"
4 0002 "some text"
.
.
. 0021-0039 Title
. 0021 "some text"
. 0022 "some text"
I think you get the point. Any chance someone can help? Thx for any help.
Perhaps you intend this:
select id, chapter, description
from t
order by left(chapter, 4),
(case when chapter like '%-%' then 1 else 2 end),
chapter;
This orders by the first four characters of the chapter, then by the chapters with the hyphens, and finally by the chapter itself. If you need for the first two values to be in the "other" order, then:
select id, chapter, description
from t
order by left(chapter, 4),
(case when chapter like '%-%' then 1 else 2 end),
(case when chapter like '%-%' then chapter end) desc,
chapter asc;
This will order by ID, then by Chapter.
IF OBJECT_ID ( 'orderedDocuments', 'P' ) IS NOT NULL
DROP PROCEDURE orderedDocuments;
GO
CREATE PROCEDURE orderedDocuments
AS
SELECT
ID, Chapter, Description
FROM
[Table Name]
ORDER BY
ID DESC
,Chapter DESC
GO

SQL query for dynamic insert row

I am having data like:
ItemCode Attribute PositionID
ITEM-000032 CHESTSIZE 1
ITEM-000032 JACKETLEN 2
ITEM-000042 CHESTSIZE 1
ITEM-000042 JACKETLEN 2
**ITEM-000049 SLACKWAIST 1**
ITEM-000071 CHESTSIZE 1
ITEM-000071 JACKETLEN 2
ITEM-000074 CHESTSIZE 1
ITEM-000074 JACKETLEN 2
In above data except ITEM-000049 others are having perfect combination. so i want to create a new row for ITEM-000049
As
ITEM-000049 -- 2
to make it perfect.
Kind regards,
Om
Sounds like for each ItemCode, you are expecting 2 records, for 2 different Attributes.
So something like this is what I think you're after. Just run the SELECT part of it first without the INSERT to check it is indeed what you're after.
INSERT YourTable (ItemCode, Attribute, PositionID)
SELECT t.ItemCode, 'SECOND ATTRIBUTE', 2
FROM
(
SELECT ItemCode
FROM YourTable
GROUP BY ItemCode
HAVING COUNT(*) = 1
) t

Counting values in columns

What I am looking for is to group by and count the total of different data in the same table and have them show in two different columns. Like below.
Data in table A
Fields:
Name Type
Bob 1
John 2
Bob 1
Steve 1
John 1
Bob 2
Desired result from query:
Name Type 1 Type 2
Bob 2 1
John 1 1
Steve 1 0
This will do the trick in SQL Server:
SELECT
name,
SUM( CASE type WHEN 1 THEN 1 ELSE 0 END) AS type1,
SUM( CASE type WHEN 2 THEN 1 ELSE 0 END) AS type2
FROM
myTable
GROUP BY
name
No time to write the code, but the Case statement is what you want here. SImply havea value of 1 if it meets the case and zero if it deosn't. Then you can sum the columns.
Use two separate GROUP BY subqueries.
SELECT Name, a.Count1, b.Count2
from myTable
JOIN
(SELECT Name, SUM(Type) AS Count1 FROM myTable GROUP BY Name WHERE Type=1) AS a ON a.Name = myTable.Name
(SELECT Name, SUM(Type) FROM myTable GROUP BY Name WHERE Type=2) AS b ON b.Name = myTable.Name
You're looking for a CrossTab solution. The above solutions will work, but you'll come unstuck if you want a general solution and have N types.
A CrossTab solution will solve this for you. If this is for quickly crunching some numbers then dump your data into Excel and use the native Pivot Table feature.
If it's for a RDBMS in an app, then it depends upon the RDBMS. MS SQL 2005 and above has a crosstab syntax. See:
http://www.databasejournal.com/features/mssql/article.php/3521101/Cross-Tab-reports-in-SQL-Server-2005.htm
#Seb has a good solution, but it's server-dependent. Here's an alternate using subselects that should be portable:
select
name,
(select count(type) from myTable where type=1 and name=a.name) as type1,
(select count(type) from myTable where type=2 and name=a.name) as type2
from
myTable as a
group by
name