Count returns null with Insert Into, but it works when I just use select in Netezza - aggregate-functions

I'm trying to insert data into a table and one of my columns is coming back null. The columns I sum are working fine, but the one I count is returning null with the insert into command followed by select. When I eliminate insert into, and just run my select statement I get the result I need. What am I doing wrong?
`
INSERT INTO DAILY_TOTALS(TIME_FRAME,
VIDEO,
DATA,
VOICE,
PREV_VIDEO,
PREV_DATA,
PREV_VOICE,
VIDEO_REVENUE,
INTERNET_REVENUE,
PHONE_REVENUE,
OCC_REVENUE,
TOTAL_REVENUE,
ACCOUNTS)
SELECT
D.TIME_FRAME,
D.VIDEO,
D.DATA,
CASE WHEN D.VOICE ='N' THEN 'N' ELSE 'Y' END AS VOICE,
D.PREV_VIDEO,
D.PREV_DATA,
CASE WHEN D.PREV_VOICE = 'N' THEN 'N' ELSE 'Y' END AS PREV_VOICE,
SUM(D.VIDEO_REVENUE) AS VIDEO_REVENUE,
SUM(D.INTERNET_REVENUE) AS INTERNET_REVENUE,
SUM(D.OCC_REVENUE) AS OCC_REVENUE,
SUM(D.TOTAL_REVENUE) AS TOTAL_REVENUE,
COUNT(D.ACCOUNT_NUMBER) AS ACCOUNTS
FROM DAILY D
WHERE D.TIME_FRAME = CURRENT_DATE -1
GROUP BY
D.TIME_FRAME,
D.VIDEO,
D.DATA,
D.VOICE,
D.PREV_VIDEO,
D.PREV_DATA,
D.PREV_VOICE`

Aren't you missing 1 column?
The INSERT statement mentions 13 columns ...but the SELECT only selects 12 columns.
So "COUNT(D.ACCOUNT_NUMBER) AS ACCOUNTS" is being inserted into the TOTAL_REVENUE column. And the ACCOUNTS column in your table is NULL because you haven't specified anything to go in there.

Related

Count(case when) redshift sql - receiving groupby error

I'm trying to do a count(case when) in Amazon Redshift.
Using this reference, I wrote:
select
sfdc_account_key,
record_type_name,
vplus_stage,
vplus_stage_entered_date,
site_delivered_date,
case when vplus_stage = 'Lost' then -1 else 0 end as stage_lost_yn,
case when vplus_stage = 'Lost' then 2000 else 0 end as stage_lost_revenue,
case when vplus_stage = 'Lost' then datediff(month,vplus_stage_entered_date,CURRENT_DATE) else 0 end as stage_lost_months_since,
count(case when vplus_stage = 'Lost' then 1 else 0 end) as stage_lost_count
from shared.vplus_enrollment_dim
where record_type_name = 'APM Website';
But I'm getting this error:
[42803][500310] [Amazon](500310) Invalid operation: column "vplus_enrollment_dim.sfdc_account_key" must appear in the GROUP BY clause or be used in an aggregate function; java.lang.RuntimeException: com.amazon.support.exceptions.ErrorException: [Amazon](500310) Invalid operation: column "vplus_enrollment_dim.sfdc_account_key" must appear in the GROUP BY clause or be used in an aggregate function;
Query was running fine before I added the count. I'm not sure what I'm doing wrong here -- thanks!
You can not have an aggregate function (sum, count etc) without group by
The syntax is like this
select a, count(*)
from table
group by a (or group by 1 in Redshift)
In your query you need to add
group by 1,2,3,4,5,6,7,8
because you have 8 columns other than count
Since I don't know your data and use case I can not tell you it will give you the right result, but SQL will be syntactically correct.
The basic rule is:
If you are using an aggregate function (eg COUNT(...)), then you must supply a GROUP BY clause to define the grouping
Exception: If all columns are aggregates (eg SELECT COUNT(*), AVG(sales) FROM table)
Any columns that are not aggregate functions must appear in the GROUP BY (eg SELECT year, month, AVG(sales) FROM table GROUP BY year, month)
Your query has a COUNT() aggregate function mixed-in with non-aggregate values, which is giving rise to the error.
In looking at your query, you probably don't want to group on all of the columns (eg stage_lost_revenue and stage_lost_months_since don't look like likely grouping columns). You might want to mock-up a query result to figure out what you actually want from such a query.

PL SQL SELECT Case Statements involving aggregate values

I'm trying to write a query that in Teradata but I'm not sure how to do it; my table looks like this:
col1: text (account_number)
col2: text (secondary account number)
col3: text (Primary_cust)
the business requirements are:
"Group records by account number.
If there is only one record for an account then keep that record.
If there are multiple records for an account number then:
(1) if only one record has Primary_CUST = 'Y' then keep.
(2) if multiple records have Primary_CUST = 'Y' then keep one with lowest SCDRY_ACCT_NBR
(3) If no records have Primary_CUST = 'Y' then keep one with lowest SCDRY_ACCT_NBR.
I know I need a CASE statement and I'm able to write the first requirement, but not sure on the second. Any help would be greatly appreciated.
You just have to think about how to order the rows to get the row you want on top, seems to be like this:
SELECT * FROM tab
QUALIFY
Row_Number()
Over (PARTITION BY account_number -- for each account
ORDER BY Primary_CUST DESC -- 'Y' before 'N' (assuming it's a Y/N column)
,SCDRY_ACCT_NBR -- lowest number
) = 1 -- return the top row
Of course QUALIFY is proprietary Teradata syntax, if you need to do this on Oracle you have to wrap it in a Derived Table:
SELECT *
FROM
(
SELECT t.*,
Row_Number()
Over (PARTITION BY account_number -- for each account
ORDER BY Primary_CUST DESC -- 'Y' before 'N' (assuming it's a Y/N column)
,SCDRY_ACCT_NBR) AS rn-- lowest number
FROM tab
) AS dt
WHERE rn = 1 -- return the top row

Aggregate Data Without Group By

I'm trying to create a single row of data, but the Group By clause is screwing me up.
Here's my table:
RegistrationPK : DateBirth : RegistrationDate
I'm trying to get the age of people at the time of Registration.
What I have is:
SELECT
CASE WHEN DATEDIFF(YEAR,DateBirth,RegistrationDate) < 20 THEN COUNT(registrationpk) END AS Under20
FROM dbo.Registration r
GROUP BY r.DOB, r.RegDate
Instead of getting one column "Under20" with one row of data, I get all the different DateBirth rows.
How can I do a DateDiff without a Group By?
Here it is:
SELECT
SUM (
CASE WHEN DATEDIFF(YEAR,DateBirth,regdate) < 20 THEN 1
ELSE 0 END
)
FROM dbo.Registration r
I got this to work, but I hate Selects within Selects. If anyone knows a simpler way I'd appreciate it. For some reason, when done as a select within a select, SQL doesn't require either statement to have the GroupBy clause.
SELECT COUNT(UNDER20) AS UNDER20
FROM (
SELECT
UNDER20 = CASE WHEN DATEDIFF(YEAR,DateBirth,regdate) < 20 THEN '1' END
FROM dbo.Registration r
) a

Sqlite Update with Substring only returns first row data

I have a table (Raw_Data) with a numerical column (WorkingData).
When I test the following SELECT I return the data I require (1st digit of the numeric value)
SELECT substr([WorkingData], 1, 1) FROM Raw_Data
I now wish to take this value & insert it into another colum in the same table so I try :-
UPDATE Raw_Data SET [FirstDigit] = (SELECT substr([WorkingData], 1, 1) FROM Raw_Data)
This code uses the first digit from the first row & places that value into every row in the the FirstDigit column. Sqlite seems to interperate the SQL command as "identify the first digit of the value found in the first row in the table & use that as the FirstDigit for every subsequent value irrespective of the actual value".
eg of UPDATE comamnd results:-
Row WorkingData First Digit
1 54987 5
2 3267 5
3 19 5
Where am I going wrong with my SQL command please?
Query
UPDATE Raw_Data SET First_Digit=SUBSTR(WorkingData, 1, 1)
WHERE Raw_Data.row=Raw_Data.row;
Screen shot

SQLite returns single row even though I am not using GROUP BY

I have the following SQLite database
I expect there will be 3 rows of result being returned, if I make the following query.
SELECT name, sum(heart) FROM test_table;
However, even though I am not using GROUP BY, only 1 row is being returned.
C:\Users\yan-cheng.cheok\Desktop>sqlite3.exe
SQLite version 3.7.13 2012-06-11 02:05:22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .restore abc
sqlite> SELECT name, sum(heart) FROM test_table;
Record3|102
I am expecting result :
Record1|102
Record2|102
Record3|102
As in convientional SQL, if I do not use GROUP BY, every individual rows will be returned.
http://www.w3schools.com/sql/sql_groupby.asp
Is there anything I can make all 3 rows returned?
Try this you can use cross join
SELECT a.name, b.totalHeart
FROM test_table a,
(
SELECT SUM(heart) totalHeart
FROM test_table
) b
This behaviour is documented:
If the SELECT statement is an aggregate query without a GROUP BY clause, then each aggregate expression in the result-set is evaluated once across the entire dataset. Each non-aggregate expression in the result-set is evaluated once for an arbitrarily selected row of the dataset. The same arbitrarily selected row is used for each non-aggregate expression. Or, if the dataset contains zero rows, then each non-aggregate expression is evaluated against a row consisting entirely of NULL values.
You could do this:
sqlite> select a.name, b.s from abc as a, (select sum(heart) as s from abc) as b;
Record1|102
Record2|102
Record3|102

Resources