Group and Sum with dynamic column names - mysql

I need to GROUP a table by Year and SUM all the possible Types (unknown) with dynamic column names.
Sample Table:
Type|Year
a 2001
a 2001
c 2002
b 2002
c 2003
a 2003
z 2003
Sample Result:
Year: 2001, Type_a: 2
Year: 2002, Type_c: 1, Type_b: 1
Year: 2003, Type_c: 1, Type_a: 1, Type_z: 1

You could group and sum types using a query like this -
SELECT year, type, COUNT(type) FROM table_name GROUP BY year, type;
It gives another result set, but with data you want.

SELECT year,COUNT(type) from tableName GROUP BY(type)
try that one

SOL is not designed for that, the result could never have a various number of column for each line.
I think the best way to get that is to change the design of your resultset with concatenation of information by example. Or having fixed number of.column filled by null or empty values.
In the other hand you can do it programmaticaly if your language allows dynamic number of column for each row.

Related

Subquery in the WHERE clause exercise

I have a migration table with attributes (name, departure year) and a stork table with attributes(name, year of birth). I want to write a query giving the names of all storks that migrated before the birth of the youngest stork which is 2002 (using the migration table in the main query and the Stork table in a sub-request of the WHERE clause). N.B: Not allowed to use a clause such as WHERE, GROUP BY, ORDER BY, LIMIT, unless it is necessary/mandatory
Migration table
Name DEPARTURE YEAR
Annamarie 2001
Felix 2002
Annamarie 2003
Felix 2004
Jonas 2001
Stork table
Name YEAROFBIRTH
Annamarie 1998
Felix 1999
Max 2000
Jonas 2001
Christina 2002
Using the DISTINCT operator gives the desired result with 15 names, removing the DISTINCT operator gives me 25 names with duplicates
SELECT DISTINCT migration.NAME
FROM migration
WHERE migration.DEPARTUREYEAR IN(SELECT stork.YEAROFBIRTH
FROM stork
WHERE stork.YEAROFBIRTH <2002)
I expect to obtain the 15 names without using the DISTINCT operator
Just going by the desired result, and your example's use of the literal year; this should be all you need.
SELECT DISTINCT migration.NAME
FROM migration
WHERE migration.DEPARTUREYEAR < 2002
;
However, if you want to not use a literal year, the subquery can be used to determine it like so:
SELECT DISTINCT migration.NAME
FROM migration
WHERE migration.DEPARTUREYEAR < (SELECT MAX(stork.YEAROFBIRTH) FROM stork)
;
Try this-
SELECT NAME -- You can apply DISTINCT if required
FROM Migration
WHERE Name IN (
SELECT Name FROM Stork
WHERE YEAROFBIRTH < 2002
)

MySQL Sum and Case Query

I create a ReportViewer with VB.NET connecting to a MySQL database. The data appears like below.
IdProduct Quantity TotalPrice OrderDate
0001 1 10 29/09/2014
0002 2 40 29/09/2014
0001 4 40 29/09/2014
0001 2 20 29/09/2014
0001 2 20 29/09/2014
Based on the records above, I'd like the result to appear like below
0001 0002
9 2
90 40
What is Query Sum Case the best use here? Thanks in advance.
NOTE: It's not possible for a query to "dynamically" alter the number or datatype of the columns returned, those must be specified at the time the SQL text is parsed.
To return the specified resultset with a query, you could do something like this:
SELECT SUM(IF(t.IdProduct='0001',t.Quantity,NULL)) AS `0001`
, SUM(IF(t.IdProduct='0002',t.Quantity,NULL)) AS `0002`
FROM mytable t
UNION ALL
SELECT SUM(IF(t.IdProduct='0001',t.TotalPrice,NULL)) AS `0001`
, SUM(IF(t.IdProduct='0002',t.TotalPrice,NULL)) AS `0002`
FROM mytable t
Note that the datatypes returned by the two queries will need to be compatible. This won't be a problem if Quantity and TotalPrice are both defined as integer.
Also, there's no specific guarantee that the "Quantity" row will be before the "TotalPrice" row; we observe that behavior, and it's unlikely that it will ever be different. But, to have a guarantee, we'd need an ORDER BY clause. So, including an additional discriminator column (a literal in the SELECT list of each query), that would give us something we could ORDER BY.
Note that it's not possible to have this single query dynamically create another column for IdProduct '0003'. We'd need to add that to the SELECT list of each query.
We could do this in two steps, using a query to get the list of distinct IdProduct, and then use that to dynamically create the query we need.
BUT... with all that said... we don't want to do that.
The normative pattern would be to return Quantity and TotalPrice as two separate columns, along with the IdProduct as another column. For example, the result returned by this statement:
SELECT t.IdProduct
, SUM(t.Quantity) AS `Quantity`
, SUM(t.TotalPrice) AS `TotalPrice`
FROM mytable t
GROUP BY t.IdProduct
And then the client application would be responsible for transforming that resultset into the desired display representation.
We don't want to push that job (of transforming the result into a display representation) into the SQL.
select idproduct, sum(quantity), sum(totalprice)
from your_table
group by idproduct

Find lowest value and coresponding code on asingle query mysql

I have a user table as follows
id name age
1 John 21
2. Mathan 23
3. Raj 21
4. Manoj 50
5 Krishnan 91
I want to find minimum age and its corresponding name. How can I do it with rails?
Can I do it in a single query?
Note: More than one names can have single age.
Is there a specific reason why you want to do it in a single query ?
If you can write 2 queries, I think you can just write :
User.where age: User.minimum(:age)
select age, group_concat(name) from table group by age order by age asc limit 1
You will need to process the results later on in ruby, but this gives all you need in one single query. Also i am assuming mysql, so might differ on other rdbms.
It gives exact output in mysql that you want try this
SELECT concat("[",name," ",age,"]") AS name
FROM TABLE
WHERE age =
(SELECT min(age)
FROM TABLE);

Filtering out some rows

I'd like to filter out some rows in SQL. This is my table.
ID | year
1 2002
1 2003
2 2003
2 2004
3 2002
I'd like to filter the ID's that has got a 2003 in the year column.
That means in this case, there will be no ID's that has got 2003 in the year column.
What is the SQL code I should use?
Your question is a bit ambiguous. One interpretation is to get the list of ids that do not contain the year 2003:
select id
from t
group by id
having sum(year = 2003) = 0
Have a look here http://www.sqlfiddle.com/#!2/bd0d6/3
select id
from dateyear
where year<> 2003
group by id
If you want to list all IDs that do not have a 2003 in the year column then year != 2003, as it was suggested by other users, won't be enough because that will return id = 2 as it contains 2004 too.
A good approach is to list get all IDs and remove from them the ones that contain 2003 in the year. You can do that this way:
SELECT DISTINCT id FROM t
WHERE id NOT IN (
SELECT id FROM t
WHERE YEAR = 2003
)
This will only output id = 3.
Fiddle here.

How can I rearrange this table using SAS or MS-Access?

I have a dataset on Microsoft Access and SAS of about a million option prices arranged with the following fields/columns:
DATE, COMPANY, PUT/CALL, PRICE
The PUT/CALL variable is an indicator variable that comes out as either PUT or CALL for each unique DATE-COMPANY combination.
Example with numbers:
DATE COMPANY PUT/CALL PRICE
2001/01/01 XOM PUT 10
2001/01/01 XOM CALL 12
2001/01/01 ABB PUT 11
2001/01/01 ABB CALL 13
What I need is for my table to be arranged with:
DATE, COMPANY, PUT PRICE, CALL PRICE
The above example with numbers, the output should be:
Example with numbers:
DATE COMPANY PUT PRICE CALL PRICE
2001/01/01 XOM 10 12
2001/01/01 ABB 11 13
Would someone know how I could use SAS, Microsoft Access or any other software to complete this?
The following works in Access:
SELECT
[DATE],
[COMPANY],
MAX(IIf([PUT/CALL]="PUT", [PRICE], NULL)) AS [PUT PRICE],
MAX(IIf([PUT/CALL]="CALL", [PRICE], NULL)) AS [CALL PRICE]
FROM [PRICES]
GROUP BY [DATE], [COMPANY];
Note that...
several of the column names have spaces or "funny characters" in them, and
DATE is a reserved word in Access,
...so the square brackets [] are important.
In SAS this is pretty easy.
Assuming your first table is a dataset named 'HAVE', and is sorted by date/company:
proc transpose data=have out=want suffix=price;
by date company;
id put_call;
var price;
run;
In Access (or SQL) you'd want to do a SQL query, something like this:
create table want as select date,company,
max(case when put_call='put' then price else null end) as put_price,
max(case when put_call='call' then price else null end) as call_price
from have group by date,company;
In SQL server you could probably do this with a pivot.