PHP Database Query - Group by month - sql

An edit per the suggestions:
$sql=
"SELECT SysproCompanyJ.dbo.InvMovements.StockCode,
SysproCompanyJ.dbo.InvMaster.Description,
SysproCompanyJ.dbo.InvMovements.TrnYear,
SysproCompanyJ.dbo.InvMovements.Warehouse,
SysproCompanyJ.dbo.InvMovements.TrnMonth,
SysproCompanyJ.dbo.InvMovements.TrnQty,
SysproCompanyJ.dbo.InvMovements.TrnValue
FROM SysproCompanyJ.dbo.InvMovements,
SysproCompanyJ.dbo.InvMaster
WHERE SysproCompanyJ.dbo.InvMovements.StockCode = SysproCompanyJ.dbo.InvMaster.StockCode
AND SysproCompanyJ.dbo.InvMovements.Warehouse = 'S2'
GROUP BY SysproCompanyJ.dbo.InvMovements.TrnMonth";
The sample DB data would be:
Stockcode | Description | TrnYear | Warehouse | TrnMonth | TrnQty | TrnValue
PN1 | Part Number 1 | 2013 | S2 | 1 | 100 | 10.00
PN2 | Part Number 2 | 2013 | S2 | 1 | 200 | 125.00
PN3 | Part Number 3 | 2013 | S2 | 1 | 200 | 60.00
PN1 | Part Number 1 | 2013 | S2 | 2 | 300 | 560.00
PN4 | Part Number 4 | 2013 | S2 | 2 | 400 | 30.00
PN5 | Part Number 5 | 2013 | S2 | 2 | 100 | 230.00
I'm trying to break down the data into separate tables grouped by month and then having a variable to sum the total TrnValue by month.
The current query as is gives the following error
Warning: odbc_exec() [function.odbc-exec]: SQL error: [Microsoft][ODBC SQL Server Driver][SQL Server]Column 'SysproCompanyJ.dbo.InvMovements.StockCode' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause., SQL state 37000 in SQLExecDirect in C:\wamp\www\dacs\S2_2.php on line 69

You can't use columns in the select statement unless they inside an aggregate function (min,max,sum,count,...) or are included in the Group By.
Try something like this:
SELECT SysproCompanyJ.dbo.InvMovements.Warehouse,
SysproCompanyJ.dbo.InvMovements.TrnYear,
SysproCompanyJ.dbo.InvMovements.TrnMonth,
Sum(SysproCompanyJ.dbo.InvMovements.TrnQty) as sum_TrnQty,
Sum(SysproCompanyJ.dbo.InvMovements.TrnValue) as sum_TrnValue
FROM SysproCompanyJ.dbo.InvMovements,
SysproCompanyJ.dbo.InvMaster
WHERE SysproCompanyJ.dbo.InvMovements.StockCode = SysproCompanyJ.dbo.InvMaster.StockCode
AND SysproCompanyJ.dbo.InvMovements.Warehouse = 'S2'
GROUP BY SysproCompanyJ.dbo.InvMovements.Warehouse,
SysproCompanyJ.dbo.InvMovements.TrnYear,
SysproCompanyJ.dbo.InvMovements.TrnMonth
Usually doesn't make sense to include varchar columns (Stockcode, Description) in any type of aggregate, and since they are different values, you probably don't want them in the Group By either.

When using GROUP BY in a SQL query, all fields shown should either be 'grouped' by or a calculated (aggregate) value.
For example;
SELECT city, count(*), avg(price) FROM properties GROUP BY city;
Which will produce something like;
City   |  count  |   Avg
Paris  |  3      |   166.666
Will count the number of rows per city. City is part of the 'group by'. 'count(*)' and 'avg(price)' are calculated columns(aggregate).
If we would introduce another column to the query, 'city';
SELECT country, city, count(*), avg(price) FROM properties GROUP BY city;
The query would give an error, because country is neither 'grouped' or a calculated value. This error is quite logical; city-names are not unique worldwide (e.g. 'Paris' USA and 'Paris' in France), so grouping by city alone, the database can not show a unique country name.
To resolve this, either include 'country' in the group by, or make it a calculated field;
SELECT country, city, count(*), avg(price) FROM properties GROUP BY country, city;
Will return the results grouped by country, then by city
Country | City | count | Avg
USA | Paris | 1 | 100.000
France | Paris | 2 | 200.000
Using a calculated value for country;
SELECT min(country), city, count(*), avg(price) FROM properties GROUP BY country, city;
Would return the results grouped by city, and the 'first' country in the group:
min(Country)| City | count | Avg
France | Paris | 3 | 166.666
Which is probably not logical; the results show 'France', but it includes results from Paris, USA

Related

Alternative to CASE Statement to Compare and Summarize Data

I have a database that looks like the following;
--------------------------------
region | price_a | price_b
--------------------------------
USA | 100 | 120
USA | 150 | 150
Canada | 300 | 300
Mexico | 20 | 25
I need to compare the values from each price column and count the matched and mismatched prices and summarize as follows:
Required Results
--------------------------------
region | price_match | price_mismatch
--------------------------------
USA | 1 | 1
Canada | 1 | 0
Mexico | 0 | 1
I can do this via multiple case statements (below) but I'm wondering if there is a better approach.
Current Code:
SELECT
region,
COUNT(CASE WHEN price_a = price_b THEN 'match' END) AS price_match,
COUNT(CASE WHEN price_a != price_b THEN 'match' END) AS price_mismatch
FROM
FOO
GROUP BY region;
I am guessing from your recent questions, you're using Snowflake, in which case you can use a more compact syntax. I still think using case expression is better from a documentation and portability standpoint;
select region,
sum(iff(price_a=price_b,1,0)) price_match,
sum(iff(price_a=price_b,0,1)) price_mismatch
from cte
group by region;
You can use sum:
select region, sum(price_a = price_b), sum(price_a != price_b)
from foo
group by region

How to get the frequency in postgresql

I have a table (table_1) like this (I have simplified it)
code | description | season
----------+------------------+--------------
500 | info 1 | fall
500 | info 4 | fall
500 | info 8 | fall
500 | info 1 | winter
300 | info 1 | spring
400 | info 1 | fall
And I want a table like below, where I have the frequency of codes in each season
season | Number of Unique Codes
----------+------------------------
fall | 2
winter | 1
spring | 1
So far I have this:
SELECT
season,
count(DISTINCT code) AS "Number of Unique Codes"
FROM table_1
WHERE code IS NOT NULL
GROUP BY season
ORDER BY code desc;
However, I am running into a few issues.
Your error is on the ORDER BY, change your ORDER BY to sort by the alias created.
SELECT
season,
count(distinct code) AS "Number of Unique Codes"
FROM table_1
WHERE code IS NOT NULL
GROUP BY season
ORDER BY "Number of Unique Codes" DESC;

SQL MIN() with GROUP BY select additional columns

I am trying to query a sql database table for the minimum price for products. I also want to grab an additional column with the value of the row with the minimum price. My data looks something like this.
ProductId | Price | Location
1 | 50 | florida
1 | 55 | texas
1 | 53 | california
2 | 65 | florida
2 | 64 | texas
2 | 60 | new york
I can query the minimum price for a product with this query
select ProductId, Min(Price)
from Table
group by ProductId
What I want to do is also include the Location where the Min price is being queried from in the above query. Is there a standard way to achieve this?
One method uses a correlated subquery:
select t.*
from t
where t.price = (select min(t2.price) from t t2 where t2.productid = t.productid);
In most databases, this has very good performance with an index on (productid, price).

Coalesce value column on basis of other column without using multiple left join

So, I have a table like this:
|---------------------|------------------|------------------|
| ID | Region |isProductAvailable|
|---------------------|------------------|------------------|
| 12 | USA | Yes |
|---------------------|------------------|------------------|
| 13 | Ohio | No |
|---------------------|------------------|------------------|
| 14 | Australia | Yes |
|---------------------|------------------|------------------|
Now, The use-case that I have is, there is a product, and it's availability is based on hierarchy that is predefined.
For example:
USA -> Ohio
Australia -> Sydney
Case 1: Now whenever I am querying in this product table, I want to check if it is available in Ohio. Since there is an entry for Ohio. The result should be returned.
Case 2: Now whenever I am querying for Sydney, the table does not contain Sydney, so it should search for it's parent in hierarchy specified above. Since there is an entry available for Australian the value for Australia should be returned.
P.S. I have solved this problem with left join and coalesce, but the problem with that is the number of left join increase as the length of specified hierarchy increases.
select coalesce(rgn_Oh.isProductAvailable,rgn_USA.isProductAvailable)
from
(select t.* from t where region = 'Ohio') rgn_Oh
left join
(select t.* from t where region = 'USA') rgn_USA
on rgn_Oh.id = rgn_USA.id;
If I understand correctly, you can use order by for this:
select t.*
from t
where region in ('USA', 'Ohio', 'Australia', 'Sydney')
order by (case region
when 'Sydney' then 1
when 'Australia' then 2
when 'Ohio' then 3
when 'USA' then 4
end)
fetch first 1 row only;

SQL Query to return a distinct count of one column while allowing a full summation of a second column, grouped by a third

I'm writing a query in access 2010 and i can't use count(distinct... so I'm running into a bit of trouble with what can be found below:
An example of my table is as follows
Provider | Member ID | Dollars | Status
FacilityA | 1001 | 50 | Pended
FacilityA | 1001 | 100 | Paid
FacilityA | 1002 | 200 | Paid
FacilityB | 1005 | 30 | Pended
FacilityB | 1009 | 90 | Pended
FacilityC | 1001 | 100 | Paid
FacilityC | 1008 | 500 | Paid
I want to return the total # of unique members that have visited each facility, but I also want to get the total dollar amount that is Pended, so for this example the ideal output would be
Provider | # members | Total Pended charges
FacilityA | 2 | 50
FacilityB | 2 | 120
FacilityC | 2 | 0
I tried using some code I found here: Count Distinct in a Group By aggregate function in Access 2007 SQL
and here:
SQL: Count distinct values from one column based on multiple criteria in other columns
Copying the code from the first link provided by gzaxx:
SELECT cd.DiagCode, Count(cd.CustomerID)
FROM (select distinct DiagCode, CustomerID from CustomerTable) as cd
Group By cd.DiagCode;
I can make this work for counting the members:
SELECT cd.Provider_Number, Count(cd.Member_ID)
FROM (select distinct Provider_Number, Member_ID from Claims_Table) as cd
ON claims_table.Provider_Number=cd.Provider_Number
Group By cd.Provider_Number;
However, no matter what I try I can't get a second portion dealing with the dollars to work without causing an error or messing up the calculation on the member count.
SELECT cd.Provider_Number,
-- claims_table.Member_ID, claims_table.Dollars
SUM(IIF ( Claims_Table.Status = 'Pended' , Claims_Table.Dollars , 0 )) as Dollars_Pending,
Count(cd.Member_ID) as Uniq_Members,
Sum(Dollars) as Dollar_Wrong
FROM (select distinct Provider_Number, Member_ID from Claims_Table) as cd inner join #claims_table
ON claims_table.Provider_Number=cd.Provider_Number and claims_table.Member_ID = cd.Member_ID
Group By cd.Provider_Number;
This should work fine based only on the table you described (named Tabelle1):
SELECT Provider, count(MemberID) as [# Members],
NZ(SUM(SWITCH([Status]='Pended', Dollars)),0) as [Total pending charges]
FROM Tabelle1
GROUP BY Provider;
Explanation
I think the first and second column are self-explanatory.
The third column is where most things are done. The SWITCH([Status]='Pended', Dollars) returns the Dollars only if the status is pending. This then gets summed up by SUM. The NZ(..,0) will set the column to 0 if the SUM returns a NULL.
EDIT: This was tested on Access 2016