SQL Command for the following table - sql

I have a table named with "Sales" having the following columns:
Sales_ID|Product_Code|Zone|District|State|Distributor|Total_Sales
Now i want to generate a sales summary to view the total sales by zone and then by district and then by State by which distributor for the last/past month period.
How can i write a Sql Statement to do this? Can anyone help me Plz. Thanks in advance.
And i have another question that, how can i select the second largest or third largest values from any column of a table.

Have a look at using the ROLLUP GROUP BY option.
Generates the simple GROUP BY aggregate rows, plus subtotal or super-aggregate rows,
and also a grand total row.
The number of groupings that is returned equals the number of expressions
in the <composite element list> plus one. For example, consider the following statement.
Copy Code
SELECT a, b, c, SUM ( <expression> )
FROM T
GROUP BY ROLLUP (a,b,c)
One row with a subtotal is generated for each unique combination of values of
(a, b, c), (a, b), and (a). A grand total row is also calculated.
Columns are rolled up from right to left.
The column order affects the output groupings of ROLLUP and can affect the number
of rows in the result set.
Something like
DECLARE #Table TABLE(
Zone VARCHAR(10),
District VARCHAR(10),
State VARCHAR(10),
Sales FLOAT
)
INSERT INTO #Table SELECT 'A','A','A',1
INSERT INTO #Table SELECT 'A','A','B',1
INSERT INTO #Table SELECT 'A','B','A',1
INSERT INTO #Table SELECT 'B','A','A',1
SELECT Zone,
District,
State,
SUM(Sales)
FROM #Table
WHERE <Your Condition here> --THIS IS WHERE YOU USE THE WHERE CLAUSE
GROUP BY ROLLUP (Zone,District,State)
To Get the second and 3rd largets, you can use either (ROW_NUMBER (Transact-SQL))
;WITH Vals AS (
SELECT *,
ROW_NUMBER() OVER (ORDER BY RequiredCol DESC) RowNum
FROM YourTable
)
SELECT *
FROM Vals
WHERE RowNum IN (2,3)
or
SELECT TOP 2
*
FROM (
SELECT TOP 3
*
FROM YourTable
ORDER BY RequiredCol DESC
) sub
ORDER BY RequiredCol

SELECT SUM(Total_Sales) FROM sales GROUP BY (X)
Replace X with Zone, District, State or Distributor.

Related

Using Derby SQL to calculate value for histogram

I have a table with various SKU in totes.
The table is totecontents with below columns:
ToteID
SKU
Each Tote can contain a maximum of 6 SKUs. (programmatically constrained)
select toteid, count(*) as qtypertote
from totecontents
group by toteid;
gives me a list of totes with the number of skus in each.
I now want to get to a table with following result
SkuCount Occurences where each row would have the ordinal value (1 through 6 ) and then the number of occurences of that value.
My efforts included the following approach
select count(*)
from
( select toteid, count(*) as qtypertote
from totecontents
group by toteid)
group by qtypertote;
Stung by the comments I performed more research. This works:
SELECT CountOfskus, COUNT(1) groupedCount
FROM
( SELECT COUNT(*) as countofskus, toteid
FROM totecontents
Group By toteid
) MyTable
GROUP BY countofskus;

How to sort varchar row by asc?

I have a column Cardnumber from Employees table. The row of a column contains the number of card: 0578391322177.
How can I sort the numbers in the row by asc and get 0112233577789?
The data type is varchar.
Ideally you would have a numbers or tally table to hand; you can build one on the fly using a CTE however.
You can join this to a substring of each character, then recombine using string_agg and order appropriately. This is assuming the card numbers are all the same length - if not adjust the CTE and include a where criteria to be <= len(string).
declare #n varchar(13)='0578391322177';
with digits as (
select *
from (
values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13)
)v(n)
)
select String_Agg(n.d,'') within group (order by n.d)
from (
select substring(#n,n,1)d
from Digits
)n
Output: 0112233577789
Edit
As an example of using with data from a table you would do
select Id, cardnumber, String_Agg(n.d,'') within group (order by n.d) SortedCardNumber
from (
select t.Id, t.cardnumber, Substring(t.cardnumber,n,1)d
from
t cross join Digits d
where d.n<=Len(t.cardnumber)
)n
group by Id, cardnumber
See DB<>Fiddle

selecting max value from table with two variable colums (microsoft SQL)

i´m working with a table that looks like this:
Start
https://i.stack.imgur.com/uibc3.png
My desired result would look like this:
Result
https://i.stack.imgur.com/v0sic.png
So i´m triyng to select the max value from two "combined" colums. If the values are the same amount (Part C), the outcome doesn't matter.
I tried to order the table by max value and then using distinct but the result didn't turn out as expected
Could you please offer a solution or some insight to this? Thanks in advance!
Use row_number():
select *
from (
select t.*, row_number() over(partition by part order by amount desc, zone) rn
from mytable t
) t
where rn = 1
For each part, this gives you the row with the highest amount; if there are top ties, column zone is used to break them.
If you want to allow ties, then use rank() instead, like:
rank() over(partition by part order by amount desc) rn
You can achieve this by using SUB Query
DECLARE #T TABLE(
PART VARCHAR(50),
ZONE VARCHAR(10),
Amt INT)
Insert Into #T Values ('PartA','71H',1),('PartA','75H',2),('PartB','98D',1),('PartB','98A',3),('PartC','75H',1),('PartC','52H',1)
SELECT M.PART,MIN(M.Zone) AS ZONE,S.AMOUNT
FROM #T M
INNER JOIN (
SELECT Part,MAX(Amt) as AMOUNT From #T
GROUP BY PART) S ON S.AMOUNT=M.Amt AND S.PART=M.PART
GROUP BY M.PART,S.AMOUNT
ORDER BY M.PART

Avg Sql Query Always Returns int

I have one column for Farmer Names and one column for Town Names in my table TRY.
I want to find Average_Number_Of_Farmers_In_Each_Town.
Select TownName ,AVG(num)
FROM(Select TownName,Count(*) as num From try Group by TownName) a
group by TownName;
But this query always returns int values. How can i get values in float too?
;WITH [TRY]([Farmer Name], [Town Name])
AS
(
SELECT N'Johny', N'Bucharest' UNION ALL
SELECT N'Miky', N'Bucharest' UNION ALL
SELECT N'Kinky', N'Ploiesti'
)
SELECT AVG(src.Cnt) AS Average
FROM
(
SELECT COUNT(*)*1.00 AS Cnt
FROM [TRY]
GROUP BY [TRY].[Town Name]
) src
Results:
Average
--------
1.500000
Without ... *1.00 the result will be (!) 1 (AVG(INT 2 , INT 1) -truncated-> INT 1, see section Return types).
Your query is always returning int logically because the average is not doing anything. Both the inner and the outer queries are grouping by town name -- so there is one value for each average, and that average is the count.
If you are looking for the overall average, then something like:
Select AVG(cast(cnt as float))
FROM (Select TownName, Count(*) as cnt
From try
Group by TownName
) t
You can also do this without the subquery as:
select cast(count(*) as float) /count(distinct TownName)
from try;
EDIT:
The assumption was that each farmer in the town has one row in try. Are you just trying to count the number of distinct farmers in each town? Assuming you have a field like FarmerName that identifies a given farmer, that would be:
select TownName, count(distinct FarmerName)
from try
group by TownName;

Get row count including column values in sql server

I need to get the row count of a query, and also get the query's columns in one single query. The count should be a part of the result's columns (It should be the same for all rows, since it's the total).
for example, if I do this:
select count(1) from table
I can have the total number of rows.
If I do this:
select a,b,c from table
I'll get the column's values for the query.
What I need is to get the count and the columns values in one query, with a very effective way.
For example:
select Count(1), a,b,c from table
with no group by, since I want the total.
The only way I've found is to do a temp table (using variables), insert the query's result, then count, then returning the join of both. But if the result gets thousands of records, that wouldn't be very efficient.
Any ideas?
#Jim H is almost right, but chooses the wrong ranking function:
create table #T (ID int)
insert into #T (ID)
select 1 union all
select 2 union all
select 3
select ID,COUNT(*) OVER (PARTITION BY 1) as RowCnt from #T
drop table #T
Results:
ID RowCnt
1 3
2 3
3 3
Partitioning by a constant makes it count over the whole resultset.
Using CROSS JOIN:
SELECT a.*, b.numRows
FROM YOUR_TABLE a
CROSS JOIN (SELECT COUNT(*) AS numRows
FROM YOUR_TABLE) b
Look at the Ranking functions of SQL Server.
SELECT ROW_NUMBER() OVER (ORDER BY a) AS 'RowNumber', a, b, c
FROM table;
You could do it like this:
SELECT x.total, a, b, c
FROM
table
JOIN (SELECT total = COUNT(*) FROM table) AS x ON 1=1
which will return the total number of records in the first column, followed by fields a,b & c