I have the following functioning query to create a crosstab/pivot table in Access
TRANSFORM Sum(y.TNAV) AS TNAV
SELECT y.RecDate
FROM BNYDaily AS y
WHERE (((y.AccName) In ("A","B")) AND y.RecDate >= DateValue("1/1/2013"))
GROUP BY y.RecDate
PIVOT y.AccName; )
The problem is that the query returns results with NULL fields that messes up my calculation. I want to omit rows in this crosstab table that have NULL value in either columns:
RecDate A B
....
1/25/2013 1,469,004,032.00 968.63
1/26/2013 1,466,082,304.00
1/28/2013 973.91
1/29/2013 1,471,277,440.00 971.66
...
I tried the following query that uses the above query as a subquery without any luck:
SELECT * FROM
(
TRANSFORM Sum(y.TNAV) AS TNAV
SELECT y.RecDate
FROM BNYDaily AS y
WHERE (((y.AccName) In ("A","B")) AND y.RecDate >= DateValue("1/1/2013"))
GROUP BY y.RecDate
PIVOT y.AccName;
) AS t
WHERE t.A IS NOT NULL AND t.B is NOT NULL
which oddly doesn't run in Access and returns an error. If I query from the crosstab query as a saved query table it works. Any ideas?
Instead of "squeezing out" the rows containing Nulls from the results of the crosstab, how about eliminating the rows that produce the Nulls from the source of the crosstab? I just tried the following and it seems to work:
TRANSFORM Sum(y.TNAV) AS TNAV
SELECT y.RecDate
FROM
(
SELECT RecDate, AccName, TNAV
FROM BNYDaily
WHERE RecDate IN (SELECT RecDate FROM BNYDaily WHERE AccName = "A")
AND RecDate IN (SELECT RecDate FROM BNYDaily WHERE AccName = "B")
) AS y
WHERE (((y.AccName) In ("A","B")) AND y.RecDate >= DateValue("1/1/2013"))
GROUP BY y.RecDate
PIVOT y.AccName;
Related
SELECT DISTINCT
Member_ID,
CASE
WHEN a.ASTHMA_MBR = 1 THEN 'ASTHMA'
WHEN a.COPD_MBR = 1 THEN 'COPD'
WHEN a.HYPERTENSION_MBR = 1 THEN 'HYPERTENSION'
END AS DX_FLAG
So a member may have more than one, but my statement is only returning one of them.
I'm using Teradata and trying to convert multiple columns of boolean data into one column. The statement is only returning one condition when members may have 2 or more. I tried using Select instead of Select Distinct and it made no difference.
This is a kind of UNPIVOT:
with base_data as
( -- select the columns you want to unpivot
select
member_id
,date_col
-- the aliases will be the final column value
,ASTHMA_MBR AS ASTHMA
,COPD_MBR AS COPD
,HYPERTENSION_MBR AS HYPERTENSION
from your_table
)
,unpvt as
(
select member_id, date_col, x, DX_FLAG
from base_data
-- now unpivot those columns into rows
UNPIVOT(x FOR DX_FLAG IN (ASTHMA, COPD, HYPERTENSION)
) dt
)
select member_id, DX_FLAG, date_col
from unpvt
-- only show rows where the condition is true
where x = 1
expected table is this:
good_days bad_days
6 25
But I have this table:
day_type x
bad_days 25
good_days 6
my code is not working:
select *
from (select * from main_table)t
pivot(count(x) for day_type in ('bad_days', 'good_days') ) as pivot_table
There are multiple ways to do this
Use postgresql extension tablefunc which contains crosstab method which can accept query result and pivot the result
You can also create a custom query (only works if you've less and known day_type column values)
WITH cte (day_type, x) AS (
VALUES ('bad_days', 25), ('good_days', 6))
SELECT sum(good_days) AS good_days,
sum(bad_days) AS bad_days
FROM (
(SELECT x AS good_days,
0 AS bad_days
FROM cte
WHERE day_type = 'good_days')
UNION ALL
(SELECT 0 AS good_days,
x AS bad_days
FROM cte
WHERE day_type = 'bad_days')) AS foo
A simple method is conditional aggregation:
select sum(x) filter (where data_type = 'bad_days') as bad_days,
sum(x) filter (where data_type = 'good_days') as good_days
from t;
I have a table with the following content (simplified):
And this is the desired result:
In short, the first column has hundreds of values and sometimes repeated, for a given value of IDPRODUCTFIRST I want a RESULT column with the given value + the values of IDPRODUCTSECOND.
SELECT IDPRODUCTSECOND AS RESULT
FROM [SCIOHIST].[dbo].[RELATIONPRODUCTMATCHES]
WHERE IDPRODUCTFIRST = 228697
With the query above, I can only get the values from the second column, how could I add to the result column the given value (e.g. 228697) from the first column?
One method is to unpivot and select distinct values:
SELECT DISTINCT v.RESULT
FROM [SCIOHIST].[dbo].[RELATIONPRODUCTMATCHES] RPM CROSS APPLY
(VALUES (IDPRODUCTFIRST), (IDPRODUCTSECOND)) V(RESULT)
WHERE IDPRODUCTFIRST = 228697;
SELECT DISTINCT IDPRODUCTFIRST AS RESULT
FROM [SCIOHIST].[dbo].[RELATIONPRODUCTMATCHES]
--WHERE IDPRODUCTFIRST = 228697
UNION
SELECT DISTINCT IDPRODUCTSECOND AS RESULT
FROM [SCIOHIST].[dbo].[RELATIONPRODUCTMATCHES]
--WHERE IDPRODUCTFIRST = 228697
where clauses can exist or not.
IF you want duplicate value in both column are in your result you can use from "UNION ALL" instead of "UNION".
You can use Union
; With cteProd
as
(
SELECT IDPRODUCTFIRST, IDPRODUCTSECOND
FROM [SCIOHIST].[dbo].[RELATIONPRODUCTMATCHES]
)
Select RESULT from
(
SELECT IDPRODUCTFIRST, IDPRODUCTFIRST AS RESULT
FROM cteProd
Union
SELECT IDPRODUCTFIRST, IDPRODUCTSECOND AS RESULT
FROM cteProd
) Q
WHERE IDPRODUCTFIRST = 228697
Here is the fiddle
Yet another option is UNPIVOT
Example
Declare #YourTable Table ([IDPRODUCTFIRST] varchar(50),[IDPRODUCTSECOND] varchar(50)) Insert Into #YourTable Values
(228697,228699)
,(228697,228701)
Select Distinct Result
From (Select [IDPRODUCTFIRST],[IDPRODUCTSECOND]
From #YourTable
Where [IDPRODUCTFIRST] = 228697
) a
Unpivot ( Result for Item in ([IDPRODUCTFIRST],[IDPRODUCTSECOND]) ) unp
Returns
Result
228697
228699
228701
I have the following query where I am querying ISIN field.
SELECT Isin FROM FundPriceDetails
WHERE Isin IN
(
'ES06139009N6' , 'MAD',
'GB0002634946' , 'LSE',
'SG1L01001701' , 'SGX'
)
The second column does not exist but I wish to show it against ISIN values without inserting the row in my select query
How do I go about doing it ? A the moment I have only ISIN in my select statement. I need to create a anonymous column that contains the next column
Use a join:
SELECT x.*
FROM (SELECT 'ES06139009N6' AS lsin, 'MAD' AS col2 UNION ALL
SELECT 'GB0002634946', 'LSE' UNION ALL
SELECT 'SG1L01001701', 'SGX'
) x JOIN
FundPriceDetails fpd
ON fpd.lsin = x.lsin;
I have the following query
SELECT ProgramDate, [CountVal]= COUNT(ProgramDate)
FROM ProgramsTbl
WHERE (Type = 'Type1' AND ProgramDate = '10/18/11' )
GROUP BY ProgramDate
What happens is that if there is no record that matches the Type and ProgramDate, I do not get any records returned.
What I like to have outputted in the above is something like the following if there is no values returned. Notice how for the CountVal we have 0 even if there are no records returned that fit the match condition:
ProgramDate CountVal
10/18/11 0
This is a little more complicated than you would like however, it is very possible. You will first have to create a temporary table of dates. For example, the query below creates a range of dates from 2011-10-11 to 2011-10-20
CREATE TEMPORARY TABLE date_stamps AS
SELECT (date '2011-10-10' + new_number) AS date_stamp
FROM generate_series(1, 10) AS new_number;
Using this temporary table, you can select from it and left join your table ProgramsTbl. For example
SELECT date_stamp,COUNT(ProgramDate)
FROM date_stamps
LEFT JOIN ProgramsTbl ON ProgramsTbl.ProgramDate = date_stamps.date_stamp
WHERE Type = 'Type1'
GROUP BY ProgramDate;
Select ProgramDate, [CountVal]= SUM(occur)
from
(
SELECT ProgramDate, 1 occur
FROM ProgramsTbl
WHERE (Type = 'Type1' AND ProgramDate = '10/18/11' )
UNION
SELECT '10/18/11', 0
)
GROUP BY ProgramDate
Because each SELECT statement is really building a table of records you can use a SELECT query to build a table with both the program count and a default count of zero. This would require two SELECT queries (one to get the actual count, one to get the default count) and using a UNION to combine the two SELECT results into a single table.
From there you can SELECT from the UNIONed table to sum the CountVals (if the programDate occurs in the ProgramTable the CountVal will be
CountVal of the first query if it exists(>0) + CountVal of the second query (=0)).
This way even if there are no records for the desired programDate in ProgramTable you will get a record back indicating a count of 0.
This would look like:
SELECT ProgramDate, SUM(CountVal)
FROM
(SELECT ProgramDate, COUNT(*) AS CountVal
FROM ProgramsTbl
WHERE (Type = 'Type1' AND ProgramDate = '10/18/11' )
UNION
SELECT '10/18/11' AS ProgramDate, 0 AS CountVal) T1
Here's a solution that works on SQL Server; not sure about other db platforms:
DECLARE #Type VARCHAR(5) = 'Type1'
, #ProgramDate DATE = '10/18/2011'
SELECT pt.ProgramDate
, COUNT(pt2.ProgramDate)
FROM ( SELECT #ProgramDate AS ProgramDate
, #Type AS Type
) pt
LEFT JOIN ProgramsTbl pt2 ON pt.Type = pt2.Type
AND pt.ProgramDate = pt2.ProgramDate
GROUP BY pt.ProgramDate
Grunge but simple and efficient
SELECT '10/18/11' as 'Program Date', count(*) as 'count'
FROM ProgramsTbl
WHERE Type = 'Type1' AND ProgramDate = '10/18/11'
Try something along these lines. This will establish a row with a date of 10/18/11 that will definitely return. Then you left join to your actual data to get your desired count (which can now return 0 if there are no corresponding rows).
To do this for more than 1 date, you'd want to build a Date table that holds a list of all dates you want to query (so substitute the "select '10/18/11'" with "select Date from DateTbl").
SELECT ProgDt.ProgDate, [CountVal]= COUNT(ProgramsTbl.ProgramDate)
FROM (SELECT '10/18/11' as 'ProgDate') ProgDt
LEFT JOIN ProgramsTbl
ON ProgDt.ProgDate = ProgramsTbl.ProgramDate
WHERE (Type = 'Type1')
GROUP BY ProgDt.ProgDate
To create a date table that you can use for querying, do this (assumes SQL Server 2005+):
create table Dates (MyDate datetime)
go
insert into Dates
select top 100000 row_number() over (order by s1.name)
from master..spt_values s1, master..spt_values s2
go