SQL null spaces in calculated columns - sql

I have created a calculated column but it is giving me a row with null value. If I add another calculated field, it adds 2 null rows, and so on.
My objective is to get a single row with a single value. No nulls.
The code:
SELECT
CLIENT_CODE,
( CASE WHEN CLITBP.TBPCODIGO=101 THEN COALESCE( CLITBP.TBPDESC2,0) ELSE NULL END) TAB101
FROM
CLIENT
GROUP BY 1,2
the wrong output
the intended output

If you want one row per client code, then you should have only one key in the GROUP BY. Perhaps this is what you want:
SELECT CLIENT_CODE,
MAX(CASE WHEN CLITBP.TBPCODIGO = 101 THEN COALESCE(CLITBP.TBPDESC2, 0) END) as TAB101
FROM CLIENT
GROUP BY CLIENT_CODE;

Related

Combine all rows in a column where most rows are null

I am writing a query trying to match true account IDs to incorrect account IDs across two tables using the following query:
SELECT DISTINCT
p.visitor_id,
CASE WHEN p.visitor_id = c.username then accountId else null end as correct_account_id,
CASE WHEN c.accountId is null then p.account_id else null end as incorrect_account_id
FROM `a_table` p
LEFT JOIN `another_table` c
ON p.account_id = c.accountID
and am getting this result (single vistor_id subset):
visitor_id
correct_account_id
incorrect_account_id
1
null
id
1
id
null
1
null
null
I would like to create one row per visitor_id where there are no null values and just the two ids are listed.
It sounds like you want:
SELECT p.visitor_id,
MAX(CASE WHEN p.visitor_id = c.username then accountId else null end) as correct_account_id,
MAX(CASE WHEN c.accountId is null then p.account_id else null end) as incorrect_account_id
FROM a_table p LEFT JOIN another_table c ON p.account_id = c.accountID
GROUP BY p.visitor_id
I removed the distinct and added the group by. Group by p.visitor_id means you want one row per visitor_id.
I wrapped your two CASE statements in MAX which means we want the maximum value (within the visitor_id grouping) there. Depending on your DB, you might need MIN instead (some DBs order nulls after other values by default, some order nulls after other values by default). Either way, the intention here is to find a non-null value for the column.
The big assumption here is that for each visitor_id, you have at most one correct_account_id and at most one incorrect_account_id that you care about. If you have more than one for the same visitor_id, this will only get one of them (the max/min). (Given that you explicitly say you want one row per visitor_id, this seems like a safe assumption.)

TSQL syntax to feed results into subquery

I'm after some help on how best to write a query that does the following. I think I need a subquery but I don't know how to use the data returned in the row to feed back into the subquery without hardcoding values? A subquery may not be the right thing here?
Ideally I only want 1 variable ...WHERE t_Date = '2018-01-01'
Desired Output:
The COUNT Criteria column has the following rules
Date < current row
Area = current row
Name = current row
Value = 1
For example, the first row indicates there are 2 records with Date < '2018-01-01' AND Area = 'Area6' AND Name = 'Name1' AND Value = 1
Example Data:
SQLFiddle: http://sqlfiddle.com/#!18/92ba3/4
Effectively I only want to return the first 2 rows but summarise the historic data into a column based on the output in that column.
The right way to do this is to use the cumulative sum functionality in ANSI SQL and SQL Server since 2012:
select t.*,
sum(case when t.value = 1 then 1 else 0 end) over (partition by t_area, t_name order by t_date)
from t;
This actually includes the current row. If you have only one row per date (for the area/name combo), then you can just subtract it or use a windowing clause:
select t.*,
sum(case when t.value = 1 then 1 else 0 end) over
(partition by t_area, t_name
order by t_date
rows between unbounded preceding and 1 preceding
)
from t;
Use a self join to find records in the same table that are related to a particular record:
SELECT t1.t_Date, t1.t_Area, t1.t_Name, t1.t_Value,
COUNT(t2.t_Name) AS COUNTCriteria
FROM Table1 as t1
LEFT OUTER JOIN Table1 as t2
ON t1.t_Area=t2.t_Area
AND t1.t_Name=t2.T_Name
AND t2.t_Date<t1.t_Date
AND t2.t_Value=1
GROUP BY t1.t_Date, t1.t_Area, t1.t_Name, t1.t_Value

How can "column in different row" be placed "different column in single row"

I want to group by two row and value of different two row of same column want to placed in different columns in a single row.below is my table
For example, I want no 1 & 2 row in a single row.In a single row,there will be ref_no(same in both row),by(LEDGERNAME whose VOUCHER_BY is Dr),to(LEDGERNAME whose VOUCHER_BY is Cr),AMOUNT(same in both row) or like this--
I used oracle database.How can i do this?
Simple. Self join:
select d.ref_no,
d.ledgername by,
c.ledgername to,
d.amount
from my_ledger_table d
inner join my_ledger_table c on d.ref_no = c.ref_no
and d.voucher_by = 'Dr'
and c.voucher_by = 'Cr'
and d.amount = c.amount;
Use GROUP BY on REF_NO,AMOUNT, so that MIN and MAX of LEDGERNAME will give you BY and TO.
Following solution should work:
SELECT REF_NO,min(LEDGERNAME) as 'BY',MAX(LEDGERNAME) as 'TO',AMOUNT
FROM [yourtable]
GROUP BY REF_NO,AMOUNT
I would go one step further to he solution by Kumar_Vikas. It appears the poster wants the "BY" column when the voucher_by is Dr and when it is Cr it should go into the column "TO".
SELECT REF_NO as ref_no
,max(case when voucher_by='Dr' then LEDGERNAME end) as 'BY'
,MAX(case when voucher_by='Cr' then LEDGERNAME end) as 'TO'
,MAX(AMOUNT) as Amount
FROM [yourtable]
GROUP BY REF_NO

Counting multiple columns with the same criteria

I would like to count multiple columns based on their contents. Each column I want to count(alpha,bravo and charlie) has either 'T' or 'F', I only want to count those with a 'T'.
So far i have:
select t1.name, count(t1.alpha), count(t1.bravo), count(t1.charlie)
from t1
where alpha='T',
or bravo='t'
or charlie='t'
group by name
order by name asc;
However the figures i am getting dont match what I get if i run
select count(*)
from t1
where name='test'
and alpha='t';
this example would need to be run in 16 different configurations to get the results i am seeking hence it not being a practical solution to write multiple versions of it.
Remove the where clause and use Conditional Aggregate instead, which will help you to count the rows only when data is T.
select t1.name,
count(case when t1.alpha ='T' then 1 end),
count(case when t1.bravo='T' then 1 end),
count(case when t1.charlie='T' then 1 end)
from t1
group by name
order by name asc;

How to group the outcomes of a query by the values in another column?

I have a table called vegetation with 2 columns:
type, count
I want to sum the count for all the rows where count value is smaller than the average count and all those for which it is higher.
I don't know how to reflect this in the group by clause... (or somewhere else?).
I guess that another way of doing it should be by assigning a value to all less-than-average data and another value to all higher-than-average data and then group by this value. But I just started and can not figure out how to do that either.
SELECT sum(CASE WHEN ct <= x.avg_ct THEN ct ELSE 0 END) AS sum_ct_low
,sum(CASE WHEN ct > x.avg_ct THEN ct ELSE 0 END) AS sum_ct_hi
FROM vegetation v
,(SELECT avg(ct) AS avg_ct FROM vegetation) x
The average is a single value, you can just CROSS JOIN the subquery to the base table (comma separated list of tables means cross-joining).
Then filter with a simple CASE statement.
I use ct instead of count, since that's a reserved word in SQL.