Is there a way in Teradata convert rows into columns without changing query for new values - dynamic

I am looking to convert rows to column for a requirement like sum of sales per year. A table like this can be transposed as follows:
Sales Year
100 2,005
200 2,005
300 2,006
100 2,007
200 2,006
300 2,007
'2005' '2006' '2007'
300 500 400
The query I used is
SELECT * FROM test1 PIVOT (SUM("s") FOR "y" IN ( '2005', '2006', '2007' ) ) AS Temp_pivot
However if a new year appears, say 2008 I need to modify the query.
Can I get the output for additional years without modifying the query. Can we do it without procedure or dynamic SQL?
Best Regards
Vaidy

It looks like you can use a sub-query in the IN clause, so what about something like:
SELECT *
FROM test1 PIVOT (
SUM("s") FOR "y" IN (
SELECT year_of_calendar
FROM sys_calendar.calendar
WHERE year_of_calendar >= 2005
-- '2005', '2006', '2007'
)
) AS Temp_pivot
I haven't tested it out, but give it a try and let me know.
TD Manual - Pivot

Thanks for the inputs.
Ravioli, I tried the subquery option but it says "select failed. 3669 more than one value was returned by a subquery".
Any other thoughts?
Best Regards
Vaidy

Related

Calculate percentages in SQL based on data in the same column, for every two rows?

For the following view, I need to calculate the percentage of errors per day. How would I merge every two rows into one, displaying a percentage of the 404 errors out of the total of each pair?
DATE | STATUS | TOTAL
2017-01-01 200 OK 250
2017-01-01 404 NOT FOUND 180
2017-01-02 200 OK 700
2017-01-02 404 NOT FOUND 25
I would like to return this as:
DATE | ERRORS (percent)
2017-01-01 41.8
2017-01-02 3.4
I have tried all kinds of parenthesis and counts, but everything I try throws different errors for syntax, or just ends up hanging and not returning anything.
I started learning SQL yesterday - I have seen similar questions answered for merging two rows into one, but I could not seem to find one for this particular situation where every two rows were merged.
Thanks!
Try something like this:
Select DATE
, SUM (
CASE WHEN STATUS IN ('404 NOT FOUND', 'OTHER ERROR STATUSES' )
THEN 1 ELSE 0 END ) -- NUMERATOR - Counts Any Errors
/
( COUNT(*) * 1.0 ) -- DENOMINATOR - Counts All Rows
AS ERRORS
FROM TABLE
GROUP BY DATE
You could make a Common Table Expression (CTE) that calculates the total for each day and then join this to just the table filtered for just '404 NOT FOUND'
WITH CTE
AS
(
SELECT
DATE,
SUM(TOTAL) as day_total
FROM Table
GROUP BY DATE
)
SELECT
T1.DATE,
(T1.TOTAL/CTE.day_total) AS ERRORS
FROM Table AS T1
LEFT JOIN CTE ON T1.DATE=CTE.DATE
WHERE T1.STATUS='404 NOT FOUND';
I tried something like this,
SELECT DATE, (SELECT COUNT(*) FROM TABLE WHERE STATUS IN ('404 NOT FOUND',
'OTHER ERROR STATUSES')) * 1.0 / COUNT(*) * 100 AS ERRORS_PERCENT
FROM TABLE
GROUP BY DATE;

IN Clause issue

I have one SQL output table like this
ITEM,LOC,PERIOD,QUANTITY
101,US,07/22/2015,500
101,US,07/02/2015,0
102,LON,07/22/2015,0
102,LON,07/02/2015,1000
But I want the output table as follows,
ITEM LOC 07/22/2015 07/02/2015
101 US 500 0
102 LON 0 1000
Please find the code which I have used below,
select * from
(
select item, loc, period, quantity
from example
)
pivot
(
sum (quantity) for period in ('22/JUL/2015','02/JUL/2015'));
If it is for 2 dates, then no issue in mentionning the 'IN' clause
If it is 1000 dates like weekly, monthly and daily. Then how ?
Below command is not working in 'IN' clause.
SELECT PERIOD FROM EXAMPLE WHERE PERIOD < TO_DATE(22/JUL/2015);
Can you please help me to solve this issue ?
Thanks for your time.
Your issue may be incompatible data types. If the period column on your table is DATE type, you are trying to compare strings/VARCHAR with DATE type.
If period column is a DATE try changing your IN to
SELECT period FROM example WHERE period < DATE '2015-07-22';
or
SELECT period FROM example WHERE period < TO_DATE('22/JUL/2015', 'DD/MON/YYYY');

SQL EXTRACT(YEAR FROM MYDATE) not a GROUP BY expression

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

SQL: Can GROUP BY contain an expression as a field?

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

How to write a sql query to sum total for each day?

Please help me to write the following sql. I have a table like this, with an amount column and date column
amount date
-----------------------
100 - 2010-02-05
200 - 2010-02-05
50 - 2010-02-06
10 - 2010-02-06
10 2010-02-07
what I want is to write a sql to get total for each day. Ultimately my query should return something like this
amount date
-----------------
300 - 2010-02-05
60 - 2010-02-06
10 - 2010-02-07
Please note that now it has group by dates and amounts are summed for that date.
RESOLVED -
This was my bad, even though I mention the date column as date here, my actual date column in postgres table was 'timestamp'. Once I changed it to get the date only, everything got working
my working sql is like this "select sum(amount), date(date)
from bills
group by date(date)
"
thanks everyone (and I will accept the 1st answer as the correct answer since I can accept only one answer)
thanks again
sameera
Pretty basic group by statement.
SELECT SUM(table.amount), table.date
FROM table
GROUP BY table.date
http://www.w3schools.com/sql/sql_groupby.asp
Look into GROUPING by date, here: http://www.w3schools.com/sql/sql_groupby.asp
and look into SUM(), here: http://www.w3schools.com/sql/sql_func_sum.asp
You will need to use both of them.
Try this:
SELECT SUM(Amount), Date FROM Table
GROUP BY Date
SELECT SUM(amount) as amount_sum, date FROM table GROUP BY date;