Select the column not like and combine column in one table [duplicate] - sql

This question already has answers here:
How to SUM two fields within an SQL query
(9 answers)
Closed 10 months ago.
My question is how can I select the currency not equal to USD and CNY and rename as others. Also, combining it into a new column AMT_Others.
ID Name Date AMT_HKD AMT_JPY AMT_USD AMT_TWD AMT_CNY
1 Amy 01/04/2022 0 5000 0 0 0
2 Bill 01/03/2022 200 0 0 0 0
3 Cathy 02/02/2022 0 0 80 2000 200
Result:
ID Name Date AMT_Others
1 Amy 01/04/2022 5000
2 Bill 01/03/2022 200
3 Cathy 02/02/2022 2000
my code: (It cannot generate what I want, what should be added? Thanks)
select ID, Name, Date, (AMT_HKD, AMT_JPY and AMT_TWD) as AMT_Others

basically add them up as long as we have only one non zero value for all currencies except USD and CNY
Select ID, Name, Date,
AMT_HKD + AMT_JPY + AMT_TWD as AMT_Others
from yourtable

You can get your desired result by using + instead of comma or AND:
SELECT id, name, ydate, amt_hkd + amt_jpy + amt_twd AS amt_others FROM yourtable;
But this is quite unpleasant in case there are null values in some of your columns. In this case, the sum would be null, too, even if some of the columns are not null. You can use COALESCE to prevent this and to force building a sum. Null values will be replaced by 0 (or another value if you change it):
SELECT id, name, ydate,
COALESCE(amt_hkd,0) + COALESCE(amt_jpy,0) + COALESCE(amt_twd,0) AS amt_others
FROM yourtable;
You can check this and see the difference between the two query results here: db<fiddle
You should also prevent table names or column names that are SQL key words, like the "date" column in your example. That'
s why I renamed it in my answer. Of course, if you can't change this, you have to live with it, but if you can, you should choose another name.

the other answers will work, unless there can be null values, if there is a row where one of these columns is ´null` then the result will also be null
select 1 + 2 -- output is 3
select 1 + 2 + null -- output is null
solution to this problem
isnull(AMT_HKD, 0) -- easy but slow
COALESCE(amt_hkd, 0) -- easy but still not the fastest solution
case when amt_hkd is null then 0 else amt_hkd end -- fastest

SELECT ID, Name, Date,
AMT_HKD + AMT_JPY + AMT_TWD as AMT_Others
FROM tb_name;
This will work

Related

SQL - split numeric into 2 columns?

I am trying to split some numeric keys in my table into separate columns (to help save space in SSAS, lower cardinality)
My data looks like the below..
LeadKey
1
2
3
5522
83746623
I want to split these into 2 columns... with 4 digits in each column. (where applicable, as anything 1>9999 won't have anything populated in the 2nd column)
So an example output of the above would be the below..
LeadKey Split1 Split2
1 1
2 2
35566 3556 6
5522 5522
83746623 8374 6623
How could I achieve this? I have split columns easily before using substring and a known character.. but never had to do a split like this. Does anyone have an approach to handle this?
Here is a solution in case you have the LeadKey numbers as int.
select LeadKey
,left(LeadKey, 4) Split1
,right(LeadKey, case when len(LeadKey)-4 < 0 then 0 else len(LeadKey)-4 end) Split2
from t
LeadKey
Split1
Split2
1
1
2
2
35566
3556
6
5522
5522
83746623
8374
6623
Fiddle
In this example, I used left for the Split1, and show the values past the 4th position for the Split2:
I've included a testing temporary table to hold our the testing values.
Feel free to adjust the code to work with your situation.
DECLARE #thelist TABLE
(
LeadKey int
);
INSERT INTO #thelist (LeadKey)
select 1 union all
select 2 union all
select 35566 union all
select 5522 union all
select 83746623
select cast(x1.LeadKey as varchar(19)),
Left(x1.LeadKey, 4) as 'Split1',
(case when len(x1.LeadKey) > 4 then right(x1.LeadKey, len(x1.LeadKey) - 4)
else '' end
) as 'Split2'
from #thelist as x1

How do I replace NULL in datediff with a text

I have a 2 different date columns and I'm using datediff to calculate the years of working. But there is nulls when the people is still working I wonder how can I replace it with a text 'Still Working'
So this is the table that I have
ID DateofHire DateofTermination
1 2011-07-05 NULL
2 2015-03-30 2016-06-16
3 2011-07-05 2012-09-24
4 2008-01-07 NULL
I have use the datediff formula and it shows like this :
DATEDIFF(year,DateofHire,DateofTermination) as 'Years of working'
ID Years_of_Working
1 NULL
2 1
3 1
4 NULL
How can I replace the NULL after I wrote a datediff query i wanted to replace it with 'Still Working'
The desired table would be like this:
ID Years_of_Working
1 Still working
2 1
3 1
4 Still Working
I assume that you will get Years_of_Working as Integer values. Replacing the attribute of the table with a different type is inconsistent.
I would just replace NULL values with 0, which would implicitly mean, that these people are still working.
So if the original table is called hire_info, then solution would look like this:
with diff_years as (
select ID,DATEDIFF(year,DateofHire,DateofTermination) as 'Years of working'
from hire_info
)
select ID, ISNULL(Years_of_Working,0) Years_of_Working
from diff_years
You can use this query. You should change the table name to your own table name.
SELECT id, if(isnull(DateofTermination),"Still working",TIMESTAMPDIFF(year,DateofHire,DateofTermination)) as 'Years of working' from date_diff;

SQL: sum 3 columns when one column has a null value without replacing null with 0?

Given table:
ID ANOTHERID ONE TWO THREE
X1 B1 15 15 -
X1 B2 10 - -
X2 B1 - 20 -
This query:
SELECT SUM (ONE + TWO + THREE) FROM (TABLE)
GROUP BY ID, ANOTHERID
I also tried
select sum(coalesce( ONE + TWO + THREE, ONE + TWO, ONE + THREE, ONE +
THREE))
at least one column has a null value. How can I still add them even if there is a null? As null and 0 have different meanings here (null means not started, 0 means not worked), I dont want to replace null with 0. Thanks
One method is:
SELECT SUM(COALESCE(ONE, 0) + COALESCE(TWO, 0) + COALESCE(THREE, 0))
FROM (TABLE)
GROUP BY ID, ANOTHERID;
Or, if you have at least one non-NULL value in each column:
SELECT SUM(ONE) + SUM(TWO) + SUM(THREE)
The time reporting table(s) should not allow null values, and the employee table should have a hire date field which can be used as criteria in your reporting queries. This will enable you to accurately report what management expects.
This solution worked for me
select
case when coalesce(sum(ONE), sum(TWO), sum(THREE)) is null then null else
sum(nvl(ONE,0) + nvl(TWO,0) + nvl(THREE,0)) end as
TOTALSUM
GROUP BY ID, ANOTHERID;
You might need to add another column in your table that describes the status of the employee (new, old) then make a condition like this:
if emp_status = 'new' then
--some code
working_hours := null;
else
--some code
working_hours : 0;
end if;

SQL Rows to Columns if column values are unknown

I have a table that has demographic information about a set of users which looks like this:
User_id Category IsMember
1 College 1
1 Married 0
1 Employed 1
1 Has_Kids 1
2 College 0
2 Married 1
2 Employed 1
3 College 0
3 Employed 0
The result set I want is a table that looks like this:
User_Id|College|Married|Employed|Has_Kids
1 1 0 1 1
2 0 1 1 0
3 0 0 0 0
In other words, the table indicates the presence or absence of a category for each user. Sometimes the user will have a category where the value if false, sometimes the user will have no row for a category, in which case IsMember is assumed to be false.
Also, from time to time additional categories will be added to the data set, and I'm wondering if its possible to do this query without knowing up front all the possible category names, in other words, I won't be able to specify all the column names I want to count in the result. (Note only user 1 has category "has_kids" and user 3 is missing a row for category "married"
(using Postgres)
Thanks.
You can use jsonb funcions.
with titles as (
select jsonb_object_agg(Category, Category) as titles,
jsonb_object_agg(Category, -1) as defaults
from demog
),
the_rows as (
select null::bigint as id, titles as data
from titles
union
select User_id, defaults || jsonb_object_agg(Category, IsMember)
from demog, titles
group by User_id, defaults
)
select id, string_agg(value, '|' order by key)
from (
select id, key, value
from the_rows, jsonb_each_text(data)
) x
group by id
order by id nulls first
You can see a running example in http://rextester.com/QEGT70842
You can replace -1 with 0 for the default value and '|' with ',' for the separator.
You can install tablefunc module and use the crosstab function.
https://www.postgresql.org/docs/9.1/static/tablefunc.html
I found a Postgres function script called colpivot here which does the trick. Ran the script to create the function, then created the table in one statement:
select colpivot ('_pivoted', 'select * from user_categories', array['user_id'],
array ['category'], '#.is_member', null);

Is there anything like an Excel IF Statement in SQL

Just wanted to see if there is a way to output a result that is not stored based on the addition of up to 4 fields?
Have a table that holds the count of passengers on a service for different categories, Adult, Child Infant and staff, and I want to try and out put a number based on the result of these fields that is not stored.
For example if the result of the add is >15 then output 45, if > 9 output 35. the output is the size of the coach that is required.
I know I can do it in Excel after the data is extracted but was wondering if it can be done before and included with the data?
Any suggestions and help appreciated.
Depending on what SQL program you're using, most offer the CASE WHEN statement (see this SQL Fiddle example)
CREATE TABLE CaseValues(
Value INT
)
INSERT INTO CaseValues
VALUES (1)
, (16)
, (9)
SELECT CASE WHEN Value > 15 THEN 45
WHEN Value BETWEEN 6 AND 14 THEN 35
ELSE 25 END AS Result
FROM CaseValues
You can also use CASE WHEN on multiple columns, see this example.
The Standard SQL CASE expression is the closest equivalent to the Excel IF(..) function:
SELECT
CASE WHEN Col1=Col2 THEN 'Foo'
WHEN Col1>Col2 THEN 'Bar'
WHEN Col3 Is NULL THEN Col4
ELSE 'unknown'
END As [CaseColumn]
FROM YourTable
You can do this with a query on the data:
select t.*,
(case when Adult + Child + Infant + staff > 15 then 45
when Adult + Child + Infant + staff > 9 then 35
end) as CoachSize
from t;
You can also do this using a view so it is available as if it were a table:
create view vw_t as
select t.*,
(case when Adult + Child + Infant + staff > 15 then 45
when Adult + Child + Infant + staff > 9 then 35
end) as CoachSize
from t;
And, in some databases, you can add a computed column directly into the table definition.
You can use a CASE statement. Here is the syntax.
SELECT
CASE WHEN DayOfBirth > 15
THEN 45
WHEN DayOfBirth > 9
THEN 35
ELSE
0
END
FROM BirthDaysTable