SQL Server - Suggest a query for this scenario - sql

In SQL Server, "I have a field (D1) as 101, 102, 103 in database table: mastersupport.
I have this query
select right(D1, R)
from mastersupport.
It will return results like 1, 2, 3
But my requirement is that I want to show result as A, B, C only instead of 1,2,3". Please suggest a query.
I tried with the below but got syntax error.
SELECT DISTINCT
REPLACE(REPLACE((RIGHT(D1, 1)), '1' , ‘A’), '2', ‘B’, ) AS ExtractString
FROM
master_support;
Any other query to derive the result as A, B, C ......

You can use a case expression:
select case right(d1, 1)
when '1' then 'A'
when '2' then 'B'
when '3' then 'C'
...
end as extract_string
from master_support
Note that if d1 is of a numeric datatype, using arithmetics seems like a more natural approach:
select case d1 % 10
when 1 then 'A'
when 2 then 'B'
when 3 then 'C'
...
end extract_string
from master_support

Related

Shouldn't this statement end with an error?

Consider the SELECT statement below:
SELECT 1, 'A'
UNION ALL
SELECT 2, 'B'
UNION ALL
SELECT 3, 'C';
The result is obvious:
1 'A'
2 'B'
3 'C'
I tried to store it as a separate table:
CREATE TABLE tmp AS
SELECT 1, 'A'
UNION ALL
SELECT 2, 'B'
UNION ALL
SELECT 3, 'C';
The contents of the tmp table are surprising:
1 'A'
2 'A'
3 'A'
Ok, that can be fixed providing explicit field names:
CREATE TABLE tmp AS
SELECT 1 AS field1, 'A' AS field2
UNION ALL
SELECT 2, 'B'
UNION ALL
SELECT 3, 'C';
Now I have a question whether the observed behavior is defined and valid. I feel that the statement without explicit field names should end with an error instead of producing a surprising result.
I'm using SQLite.

Transpose one row of a table access

I have a table where each row has a Scale Name and then 6 points representing the 6 Reponses to a survey
Scale
Point1
Point2
Point3
Point4
Point5
Point6
Ability
Extremely Unable
Moderately Unable
Somewhat Unable
Somewhat Able
Moderately Able
Extremely Able
I need to figure out how to write a query that will return:
ID
Response
1
Extremely Unable
2
Moderately Unable
3
Somewhat Unable
4
Somewhat Able
5
Moderately Able
6
Extremely Able
I've tried to do this with the crosstab query wizard and SQL but I'm not making any headway.
UPDATE - This is what I ended up with:
SELECT 1 AS ID, [Ref-SCALELIST].Point1 AS Response
FROM [Ref-SCALELIST]
WHERE ((([Ref-SCALELIST].SCALE)="Ability"))
UNION
SELECT 2 , [Ref-SCALELIST].Point2
FROM [Ref-SCALELIST]
WHERE ((([Ref-SCALELIST].SCALE)="Ability"))
UNION
SELECT 3, [Ref-SCALELIST].Point3
FROM [Ref-SCALELIST]
WHERE ((([Ref-SCALELIST].SCALE)="Ability"))
UNION
SELECT 4, [Ref-SCALELIST].Point4
FROM [Ref-SCALELIST]
WHERE ((([Ref-SCALELIST].SCALE)="Ability"))
UNION
SELECT 5, [Ref-SCALELIST].Point5
FROM [Ref-SCALELIST]
WHERE ((([Ref-SCALELIST].SCALE)="Ability"))
UNION
SELECT 6, [Ref-SCALELIST].Point6
FROM [Ref-SCALELIST]
WHERE ((([Ref-SCALELIST].SCALE)="Ability"))
;
"Ability" is going to be replaced with a variable so I can dynamically update a combo box based on which scale is selected. Convoluted, but at least I avoid creating a table or query for each scale in my list (>30)
You could try something like this:
WITH col as(
select '1' AS c
UNION ALL
select '2' AS c
UNION ALL
select '3' AS c
UNION ALL
select '4' AS c
UNION ALL
select '5' AS c
UNION ALL
select '6' AS c
)
select
c 'ID',
CASE c
when '1' then "Extremely Unable"
when '2' then "Moderately Unable"
when '3' then "Somewhat Unable"
when '4' then "Somewhat Able"
when '5' then "Moderately Able"
when '6' then "Extremely Able"
else null
END as response
FROM table1 corss join col
db fiddle link

Oracle SQL Min in Select Clause

Can some one please help me in writing a sql query that should do a oracle min function based on the following conditions.
For eg for column values
0,0,0,0 then output should be 0
0,null,0,null then output should be o
0,2,4,5,6 then output should be 2 (Note that we are excluding Zero here)
0,2,null,4,5 then output should be 2 (same here we are excluding zero)
null,null,null, null then output should be null.
I wrote query already that satisfies all the above cases but failing for last case when all the column values are null. Instead of returning null it is returning 0. Can some one modify the below query to fit for the last case as well?
select NVL(MIN(NULLIF(columnname,0)),0) from tablename;
Please also keep in mind that the query should be runnable in oracle as well as hsqldb as we are using hsql db for running junits.
If all 4 cases satisfied by your query then just a case will solve your problem.
SELECT CASE WHEN MIN(COLUMNNAME) IS NULL THEN NULL ELSE NVL(MIN(NULLIF(COLUMNNAME,0)),0) END FROM TABLENAME;
Note:- assuming all the cases satisfied by your query except 5th.
I will show below an input table with two columns, ID and VAL, to illustrate the various possibilities. You want a single result per ID (or even for the entire table), so this must be a job for GROUP BY and some aggregate function. You want to distinguish between three types of values: Greater than zero, zero, and null (in this order); you want to pick the "highest priority group" that exists for each ID (in this order of priority), and for that priority group only, you want to pick the min value. This is exactly what the aggregate FIRST/LAST function does. To order by the three "classes" of values, we use a CASE expression in the ORDER BY clause of the aggregate LAST function.
The WITH clause below is not part of the solution - I only include it to create test data (in your real life situation, use your actual table and column names and remove the entire WITH clause).
with
inputs ( id, val ) as (
select 1, 0 from dual union all
select 1, 0 from dual union all
select 1, 0 from dual union all
select 2, 0 from dual union all
select 2, null from dual union all
select 2, 0 from dual union all
select 3, 0 from dual union all
select 3, 2 from dual union all
select 3, 5 from dual union all
select 4, 0 from dual union all
select 4, 3 from dual union all
select 4, null from dual union all
select 5, null from dual union all
select 5, null from dual
)
select id,
min(val) keep (dense_rank last order by case when val > 0 then 2
when val = 0 then 1
else 0
end
) as min_val
from inputs
group by id
order by id
;
ID MIN_VAL
---------- ----------
1 0
2 0
3 2
4 3
5

use SUM on certain conditions

I have a script that extracts transactions and their details from a database. But my users complain that the file size being generated is too large, and so they asked for certain transactions to be just summed up/consolidated instead if they are of a certain classification, say Checking Accounts. That means there should only be one line in the result set named "Checking" which contains the sum of all transactions under Checking Accounts. Is there a way for an SQL script to go like:
CASE
WHEN Acct_class = 'Checking'
then sum(tran_amount)
ELSE tran_amount
END
I already have the proper GROUP BY and ORDER BY statements, but I can't seem to get my desired output. There is still more than one "Checking" line in the result set. Any ideas would be very much appreciated.
Try This,
Select sum(tran_amount) From tran_amount Where Acct_class = 'Checking'
You can try to achieve this using UNION ALL
SELECT tran_amount, .... FROM table WHERE NOT Acct_class = 'Checking'
UNION ALL
SELECT SUM(tran_amount), .... FROM table WHERE Acct_class = 'Checking' GROUP BY Acct_class, ...;
hi you can try below sql
select account_class,
case when account_class = 'saving' then listagg(trans_detail, ',') within group (order by emp_name) -- will give you all details transactions
when account_class = 'checking' then to_char(sum(trans_detail)) -- will give you only sum of transactions
end as trans_det from emp group by account_class;
Or, if your desired output is getting either the sum, either the actual column value based on another column value, the solution would be to use an analytical function to get the sum together with the actual value:
select
decode(acct_class, 'Checking', tran_amount_sum, tran_amount)
from (
select
sum(tran_amount) over (partition by acct_class) as tran_amount_sum,
tran_amount,
acct_class
from
YOUR_TABLE
)
You can try something like the following, by keeping single rows for some classes, and aggregating for some others:
with test (id, class, amount) as
(
select 1, 'a' , 100 from dual union all
select 2, 'a' , 100 from dual union all
select 3, 'Checking', 100 from dual union all
select 4, 'Checking', 100 from dual union all
select 5, 'c' , 100 from dual union all
select 6, 'c' , 100 from dual union all
select 7, 'c' , 100 from dual union all
select 8, 'd' , 100 from dual
)
select sum(amount), class
from test
group by case
when class = 'Checking' then null /* aggregates elements of class 'b' */
else id /* keeps elements of other classes not aggregated */
end,
class

Microsoft SQL between statement for characters is not inclusive?

I am trying to select all values that have a first name beginning with the letters a-d, however when I do this
select * from tblprofile where firstname between 'a' and 'd'
I get all values from a to c, not including d, how can I make sure it includes d?
It is inclusive.
You don't get the results you want because any string beginning with 'd' and longer than 1 character is greater than 'd'. For example 'da' > 'd'.
So, your query would return all values starting with 'a', 'b', 'c', and a value 'd'.
To get the results you want use
select * from tblprofile where firstname >= 'a' and firstname < 'e'
Try using Left() Function:
SELECT *
FROM tblprofile
WHERE LEFT(FirstName,1) between 'a' and 'd'
Another way is using a union select like this
SELECT * FROM tblprofile WHERE LEFT(FirstName,1) = 'a'
union
SELECT * FROM tblprofile WHERE LEFT(FirstName,1) = 'b'
union
SELECT * FROM tblprofile WHERE LEFT(FirstName,1) = 'c'
union
SELECT * FROM tblprofile WHERE LEFT(FirstName,1) = 'z'
The advantage of using union is if you need to get the results stating with A, K and X, strings out of sequence.