Hopefully this is pretty simple, but I'm having some trouble. I have a table that has multiple fields but basically the two that matter are ID and year. A single ID can exist in many years. How do I set up a select statement (Which I'm ultimately using in a join in another statement) so that I can retrieve all of the distinct IDS with no duplicates for the top year that they exist for?
If there is a set of records like this:
ID - Year
55 - 2000
55 - 2001
56 - 2000
56 - 2002
So basically I want something like this returned:
55 - 2001
56 - 2002
Help?
SELECT ID, MAX(Year) FROM MyTable GROUP BY ID
References:
SELECT (Transact-SQL)
GROUP BY (Transact-SQL)
Aggregate Functions (Transact-SQL)
MAX (Transact-SQL)
Related
Below is my data set
Year Month Holiday list
----------------------------------------------------------
2007 1 WWHHWWWWWHHWWWWWHHWWWWWHHWWWWWH
2008 4 HWWWWWHHWWWWWHHWWWWWHHWWWWWHHWW
I want to write SQL query to get below output wherein the position of each "H" is displayed.
Year Month Holiday list
-----------------------------------------------------
2007 1 3 4 10 11 18 19 25 26 31
2008 4 1 7 8 14 15 21 22 28 29
The INSTR function in Oracle returns the position of first character. So, I cannot use it.
I could write a Function and pass the Holiday List column value to it. Loop through the string and
find the position of each "H". But, I want to achieve this through plain SQL select query.
How to find each position of same characters in a string through SQL query in Oracle database?
Something like this might do it. You can use the INSTRfunction and a hierarchical query to go through the string and then use the LISTAGG analytic function to concatenate the results.
WITH data AS (
SELECT 2007 year, 1 month, 'WWHHWWWWWHHWWWWWHHWWWWWHHWWWWWH' holiday_list FROM DUAL
UNION
SELECT 2008 year, 4 month, 'HWWWWWHHWWWWWHHWWWWWHHWWWWWHHWW' holiday_list FROM DUAL)
SELECT year, month, (SELECT LISTAGG(INSTR(holiday_list,'H',1,LEVEL),' ') WITHIN GROUP (ORDER BY LEVEL)
FROM DUAL
CONNECT BY LEVEL < INSTR(holiday_list,'H',1,LEVEL)) S
FROM data;
Well you can get a list, see the dbfiddle here
SELECT id, INSTR(some, 'H', 1, c.no) AS Pos
FROM tst CROSS JOIN consecutive c
WHERE INSTR(some, 'H', 1, c.no) > 0
This gives you a list of the days with an H. You could then try to transpose this list. But be warned, there is an intentional CROSS JOIN there, so for every row in your data you will get up to 31 rows with this statement. Like Tim Biegeleisen said, it may be better to use an UDF for this.
I have table MYTABLE with columns mydate and quantity of VARCHAR2 type.
|mydate| |quantity|
10/15/2010 15
01/20/2010 20
05/16/2005 30
04/29/2005 50
03/30/2008 5
I want to get:
|year| |quantity|
2010 35
2005 80
2008 5
I try:
SELECT
to_char(mydate,'yyyy') YEAR,
SUM(to_number(quantity))
FROM MYTABLE
GROUP BY
to_char(mydate,'yyyy');
But I get an error
ORA-00979: not a GROUP BY expression
What did I do wrong?
You must put all columns of the SELECT in the GROUP BY or use functions on them which compress the results to a single value (like MIN, MAX or SUM).
A simple example to understand why this happens: Imagine you have a database like this:
FOO BAR
0 A
0 B
and you run SELECT * FROM table GROUP BY foo. This means the database must return a single row as result with the first column 0 to fulfill the GROUP BY but there are now two values of bar to chose from. Which result would you expect - A or B? Or should the database return more than one row, violating the contract of GROUP BY?
Try this
select extract(year from mydate),sum(to_number(quant)) from mytable
group by extract(year from mydate);
SQLFiddle Example
I'm having difficulty pinning down the proper syntax to get a total I need from Oracle 11g. I need to produce a total based on values in column 2, independent of the values in column 1. I've tried several types of rollup, cube, grouping sets, but I keep getting totals for each grade level (values in column 1).
Here is the 'group by' without any subtotaling:
... sql select statement ...
...
GROUP BY grade, inc_count
ORDER BY grade
which produces
9 714
10 550
11 445
12 296
And here is my goal output:
9 714
10 550
11 445
12 296
2005
Which permutation of rollup/group sets/or something else will get me to my goal output?
You could try doing a UNION ALL to this SELECT 'SUM', SUM(value) from TABLE
For the example you gave:
select grade, sum(cnt)
from t
group by cube(grade)
order by sum(cnt);
group by cube is "syntactic sugar" for:
group by grouping sets ((grade),())
I want to group a set of dated records by year, when the date is to the day. Something like:
SELECT venue, YEAR(date) AS yr, SUM(guests) AS yr_guests
FROM Events
...
GROUP BY venue, YEAR(date);
The above is giving me results instead of an error, but the results are not grouping by year and venue; they do not appear to be grouping at all.
My brute force solution would be a nested subquery: add the YEAR() AS yr as an extra column in the subquery, then do the grouping on yr in the outer query. I'm just trying to learn to do as much as possible without nesting, because nesting usually seems horribly inefficient.
I would tell you the exact SQL implementation I'm using, but I've had trouble discovering it. (I'm working through the problems on http://www.sql-ex.ru/ and if you can tell what they're using, I'd love to know.) Edited to add: Per test in comments, it is probably not SQL Server.
Edited to add the results I am getting (note the first two should be summed):
venue | yr | yr_guests
1 2012 15
1 2012 35
2 2012 12
1 2008 15
I expect those first two lines to instead be summed as
1 2012 50
Works Fine in SQL Server 2008.
See working Example here: http://sqlfiddle.com/#!3/3b0f9/6
Code pasted Below.
Create The Events Table
CREATE TABLE [Events]
( Venue INT NOT NULL,
[Date] DATETIME NOT NULL,
Guests INT NOT NULL
)
Insert the Rows.
INSERT INTO [Events] VALUES
(1,convert(datetime,'2012'),15),
(1,convert(datetime,'2012'),35),
(2,convert(datetime,'2012'),12),
(1,convert(datetime,'2008'),15);
GO
-- Testing, select newly inserted rows.
--SELECT * FROM [Events]
--GO
Run the GROUP BY Sql.
SELECT Venue, YEAR(date) AS yr, SUM(guests) AS yr_guests
FROM Events
GROUP BY venue, YEAR(date);
See the Output Results.
VENUE YR YR_GUESTS
1 2008 15
1 2012 50
2 2012 12
it depends of your database engine (or SQL)
to be sure (over different DB Systems & Versions), make a subquery
SELECT venue, theyear, SUM(guests) from (
SELECT venue, YEAR(date) AS theyear, guest
FROM Events
)
GROUP BY theyear
you make a subtable of
venue, date as theyear, guest
aaaa, 2001, brother
aaaa, 2001, bbrother
bbbb, 2001, nobody
... and so on
and then
count them
I have a question regarding Oracle SQL.
My data looks like this:
id year
-- ----
1 2000
1 2001
1 2002
1 2003
1 2006
1 2000
2 2001
2 2002
2 2003
3 2003
3 2005
4 2012
4 2013
I want the id's which have the years 2001, 2002, 2003.
My result set:
id
--
1
2
Please help me with this. I actually tried searching this, but couldn't figure a way to search about my particular problem.
SQL
SELECT t.id
FROM TABLE t
WHERE t.year in(2001,2002,2003)
GROUP BY t.id
Sample SqlFiddle
http://sqlfiddle.com/#!2/4ec9f/2/0
Explanation
You want to filter your data set to only show rows with certain years, so that is what you put in the where clause WHERE t.year in(2001,2002,2003).
Since a single id can be in multiple years, your result set would contain duplicates. To remove the duplicates you could GROUP BY the ID or use the DISTINCT statement to only show unique elements.
UPDATE
Based on comments, here's a version that will only display id's that have all three years. We use DISTINCT t.YEAR to avoid counting id's that perhaps would have a single year repeated multiple times. The HAVING COUNT(DISTINCT t.YEAR) = 3 part ensures that we only include id's that have all three years.
SELECT t.id
FROM years t
WHERE t.year in(2001,2002,2003)
GROUP BY t.id
HAVING COUNT(DISTINCT t.YEAR) = 3
Updated sqlFiddle, which includes a data set where id of 3 has two rows for 2003 to show off the logic that only counts unique years for an ID.
select distinct id
from table
where year in(2001,2002,2003)