Avg Sql Query Always Returns int - sql

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;

Related

Keeping Unique Rows with Group By Cube

Suppose I have data that includes the SSN of a student, the college campus they attended, and their wages for a given year. Like so...
create table #thetable (SSN int, campus int, wage int);
insert into #thetable(SSN, campus, wage)
values
(111111111,1,100),
(111111111,2,100),
(222222222,1,250),
(222222222,2,250),
(333333333,1,50),
(444444444,2,400);
Now, I want to get the average wage of the students at each campus, and the average wage of students from all campuses put together... So I do something like this:
select campus, avg(wage)
from #thetable
group by cube(campus);
The problem is that I don't want to double-count the students who attended two campuses when I'm grouping the campuses together. This is the output I'm getting (double counts students 111111111 and 2222222222):
Campus (no column name)
1 133
2 250
NULL 191
My desired output is this (no double counting):
Campus (no column name)
1 133
2 250
NULL 200
Can this be accomplished without using multiple queries and the UNION operator? If so, how? (Incidentally, I realize that this table is not normalized... would normalizing help?)
You can't do this with one column. The cube is going to rollup the values based on the calculations on each line. So, if a row is included in one calculation, it will be included in the sum.
You can do this, though, by weighting the values by 1 divided by the frequency. This "divides" a student equally across the campuses to each adds to 1:
select campus, avg(wage) as avg_wage, sum(wage*weight) / sum(weight) avg_wage_weighted
from (select t.*, (1.0 / count(*) over (partition by SSN)) as weight
from #thetable t
) t
group by cube(campus);
The second column should be the value you want. You can then embed this further in a subquery to get one column:
select campus, (case when campus is null then avg_wage_weighted else avg_wage end)
from (select campus, avg(wage) as avg_wage, sum(wage*weight) / sum(weight) avg_wage_weighted
from (select t.*, (1.0 / count(*) over (partition by SSN)) as weight
from #thetable t
) t
group by cube(campus)
) t
Here is a SQL Fiddle showing the solution.
Figured it out with a correlated sub-query. Works for me.
select campus,
(
select avg(wage)
from
(
select ssn, campus, wage, row_number() over(partition by SSN order by wage) as RN
from #thetable as inside
where (inside.campus=outside.campus or outside.campus is null)
) as middle
where RN=1
)
from #thetable outside
group by cube(campus);

Count distinct value pairs in multiple columns in SQL

What query will count the number of rows, but distinct by three parameters?
Example:
Id Name Address
==============================
1 MyName MyAddress
2 MySecondName Address2
Something like:
select count(distinct id,name,address) from mytable
To get a count of the number of unique combinations of id, name and address:
SELECT Count(*)
FROM (
SELECT DISTINCT
id
, name
, address
FROM your_table
) As distinctified
Get all distinct id, name and address columns and count the resulting rows.
SELECT COUNT(*) FROM mytable GROUP BY id, name, address
Another (probably not production-ready or recommended) method I just came up with is to concat the values to a string and count this string distinctively:
SELECT count(DISTINCT concat(id, name, address)) FROM mytable;
You can also do something like:
SELECT COUNT(DISTINCT id + name + address) FROM mytable
Having to return the count of a unique Bill of Materials (BOM) where each BOM have multiple positions, I dd something like this:
select t_item, t_pono, count(distinct ltrim(rtrim(t_item)) + cast(t_pono as varchar(3))) as [BOM Pono Count]
from BOMMaster
where t_pono = 1
group by t_item, t_pono
Given t_pono is a smallint datatype and t_item is a varchar(16) datatype

select max, min values from two tables

I have two tables. Differ in that an archive is a table and the other holds the current record. These are the tables recording sales in the company. In both we have among other fields: id, name, price of sale. I need to select from both tables, the highest and lowest price for a given name. I tried to do with the query:
select name, max (price_of_sale), min (price_of_sale)
from wapzby
union
select name, max (price_of_sale), min (price_of_sale)
from wpzby
order by name
but such an inquiry draws me two records - one of the current table, one table archival. I want to chose a name for the smallest and the largest price immediately from both tables. How do I get this query?
Here's two options (MSSql compliant)
Note: UNION ALL will combine the sets without eliminating duplicates. That's a much simpler behavior than UNION.
SELECT Name, MAX(Price_Of_Sale) as MaxPrice, MIN(Price_Of_Sale) as MinPrice
FROM
(
SELECT Name, Price_Of_Sale
FROM wapzby
UNION ALL
SELECT Name, Price_Of_Sale
FROM wpzby
) as subQuery
GROUP BY Name
ORDER BY Name
This one figures out the max and min from each table before combining the set - it may be more performant to do it this way.
SELECT Name, MAX(MaxPrice) as MaxPrice, MIN(MinPrice) as MinPrice
FROM
(
SELECT Name, MAX(Price_Of_Sale) as MaxPrice, MIN(Price_Of_Sale) as MinPrice
FROM wapzby
GROUP BY Name
UNION ALL
SELECT Name, MAX(Price_Of_Sale) as MaxPrice, MIN(Price_Of_Sale) as MinPrice
FROM wpzby
GROUP BY Name
) as subQuery
GROUP BY Name
ORDER BY Name
In SQL Server you could use a subquery:
SELECT [name],
MAX([price_of_sale]) AS [MAX price_of_sale],
MIN([price_of_sale]) AS [MIN price_of_sale]
FROM (
SELECT [name],
[price_of_sale]
FROM [dbo].[wapzby]
UNION
SELECT [name],
[price_of_sale]
FROM [dbo].[wpzby]
) u
GROUP BY [name]
ORDER BY [name]
Is this more like what you want?
SELECT
a.name,
MAX (a.price_of_sale),
MIN (a.price_of_sale) ,
b.name,
MAX (b.price_of_sale),
MIN (b.price_of_sale)
FROM
wapzby a,
wpzby b
ORDER BY
a.name
It's untested but should return all your records on one row without the need for a union
SELECT MAX(value) FROM tabl1 UNION SELECT MAX(value) FROM tabl2;
SELECT MIN(value) FROM tabl1 UNION SELECT MIN(value) FROM tabl2;
SELECT (SELECT MAX(value) FROM table1 WHERE trn_type='CSL' and till='TILL01') as summ, (SELECT MAX(value) FROM table2WHERE trn_type='CSL' and till='TILL01') as summ_hist

SQL Command for the following table

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.

Selecting COUNT(*) with DISTINCT

In SQL Server 2005 I have a table cm_production that lists all the code that's been put into production. The table has a ticket_number, program_type, program_name and push_number along with some other columns.
GOAL: Count all the DISTINCT program names by program type and push number.
What I have so far is:
DECLARE #push_number INT;
SET #push_number = [HERE_ADD_NUMBER];
SELECT DISTINCT COUNT(*) AS Count, program_type AS [Type]
FROM cm_production
WHERE push_number=#push_number
GROUP BY program_type
This gets me partway there, but it's counting all the program names, not the distinct ones (which I don't expect it to do in that query). I guess I just can't wrap my head around how to tell it to count only the distinct program names without selecting them. Or something.
Count all the DISTINCT program names by program type and push number
SELECT COUNT(DISTINCT program_name) AS Count,
program_type AS [Type]
FROM cm_production
WHERE push_number=#push_number
GROUP BY program_type
DISTINCT COUNT(*) will return a row for each unique count. What you want is COUNT(DISTINCT <expression>): evaluates expression for each row in a group and returns the number of unique, non-null values.
I needed to get the number of occurrences of each distinct value. The column contained Region info.
The simple SQL query I ended up with was:
SELECT Region, count(*)
FROM item
WHERE Region is not null
GROUP BY Region
Which would give me a list like, say:
Region, count
Denmark, 4
Sweden, 1
USA, 10
You have to create a derived table for the distinct columns and then query the count from that table:
SELECT COUNT(*)
FROM (SELECT DISTINCT column1,column2
FROM tablename
WHERE condition ) as dt
Here dt is a derived table.
SELECT COUNT(DISTINCT program_name) AS Count, program_type AS [Type]
FROM cm_production
WHERE push_number=#push_number
GROUP BY program_type
try this:
SELECT
COUNT(program_name) AS [Count],program_type AS [Type]
FROM (SELECT DISTINCT program_name,program_type
FROM cm_production
WHERE push_number=#push_number
) dt
GROUP BY program_type
You can try the following query.
SELECT column1,COUNT(*) AS Count
FROM tablename where createddate >= '2022-07-01'::date group by column1
This is a good example where you want to get count of Pincode which stored in the last of address field
SELECT DISTINCT
RIGHT (address, 6),
count(*) AS count
FROM
datafile
WHERE
address IS NOT NULL
GROUP BY
RIGHT (address, 6)