SQL - Find the binary representation from the place of '1's - sql

It is really hard to find a good title for this.
Here is the question: I have a SELECT query GROUP BY a field which returns me up to three values (1,2,3). These values are representing the positions of '1' in a binary number.
In other words:
Query Output | Reult
0,1,2 | 7 (111)
1,2 | 6 (110)
3 | 1 (001)
- | 0 (000)
Ok, I know it is easy. But there are two constraints. First, I want a query not a function/store procedure. Second, the result should be a string (like '010') not the number.
I found the solution for integer value, but not the string (varchar)
SELECT COALESCE(sum(power(2, field)), 0) AS test FROM (
SELECT field FROM myTable GROUP BY field) a
I am using SQL server 2008, just in case.
I also have this solution, but this one cannot be extended to bigger number of outputs:
SELECT output =
CASE TEST
WHEN 0 THEN '000'
WHEN 1 THEN '001'
WHEN 2 THEN '010'
WHEN 3 THEN '011'
WHEN 4 THEN '100'
WHEN 5 THEN '101'
WHEN 6 THEN '110'
WHEN 7 THEN '111'
END
FROM(
select COALESCE(sum(power(2, 3 - field)), 0) as test from (
select field from myTable group by field) a) b

You can use binary and and string concatenation:
select (case when test&4 > 0 then '1' else '0' end) +
(case when test&2 > 0 then '1' else '0' end) +
(case when test&1 > 0 then '1' else '0' end)
from (select 6 as test) t;
If you are allergic to case statements, you could do this:
select CHAR(ascii(0) + (test&4)/4) +
CHAR(ascii(0) + (test&2)/2) +
CHAR(ascii(0) + (test&1)/1)
from (select 6 as test) t

Related

Conditional SUM with SELECT statement

I like to sum values in a table based on a condition taken from the same table called. The structure of the table as per below. The table is called Data
Data
Type Value
1 5
1 10
1 15
1 25
1 15
1 20
1 5
2 10
3 5
If the Value of Type 2 is larger than the Value of Type 3 then I like to subtract the Value of Type 2 from the sum of all the Values in the table. I'm not sure how to write the IF statements using Values looked up in the table. I have tried below but it doesn't work.
SELECT SUM(Value)-IF(SELECT Value FROM Data WHERE Type=2>SELECT Value
FROM Data WHERE Type=3 THEN SELECT Value FROM Data
WHERE Type=2 ELSE SELECT Value FROM Data WHERE Type=3) FROM Data
or
SELECT SUM(d.Value)-IIF(a.type2>b.type3, a.type2, b.type3)
FROM Data d, (SELECT Value AS type2 FROM Data WHERE Type=2) a,
(SELECT Value AS type3 FROM Data WHERE Type=3) b
If I follow your logic correctly, then this would seem to do what you want:
select d.value - (case when d2.value > d3.value then d2.value else 0 end)
from data d cross join
(select value from data where type = 2) d2 cross join
(select value from data where type = 3) d3 ;
EDIT:
If you want just one number, then use conditional aggregation:
select sum(value) -
(case when sum(case when type = 2 then value else 0 end) >
sum(case when type = 3 then value else 0 end)
then sum(case when type = 2 then value else 0 end)
else 0
end)
from data;
Thanks for pointing me in the right direction. This is what I came up with in the end. It is a little bit different to the reply above since I'm using MS Access
SELECT SUM(Value)-IIf(SUM(IIf(Type=2, Value, 0)>SUM(IIf(Type=3, Value, 0), SUM(IIf(Type=2, Value, 0), SUM(IIf(Type=3, Value, 0) FROM Data
It is them same as the second suggestion above but adapted to MS Access SQL.

How to Insert Select statments in Case clause in SQL [duplicate]

This question already has answers here:
SQL Case Expression Syntax?
(8 answers)
Closed 7 years ago.
SQL knowledge Beginner
I have a below table: ScoreTable
Name Score Reason Subject
a1 0 NULL NULL
a2 -1 NULL NULL
a3 -3 fail Maths
a4 -3 fail History
a3 0 NULL NULL
I want to write a query which will look some thing like below
Select DISTINCT Name, Result,
(If Result = -3
then Concat(Reason,' ',Subject))As FailedIn)
From ScoreTable
Expected Output:
Name Score FailedIn
a1 0 0
a2 -1 0
a3 -3 fail Maths
a4 -3 fail History
You probably don't want to put "0" and a string in the same column. It is better to use NULL. So:
Select Name, Result,
(case when Result = -3 then Reason + ' ' + Subject
end) as FailedIn
It is unclear why the last row disappears, but perhaps you want something like:
Select Name, min(Result),
(case when min(Result) = -3 then max(Reason + ' ' + Subject)
end) as FailedIn
from table t
group by name
Try using CASE..WHEN..THEN like below and use minimum result score :
SELECT Name, MIN(Result)
CASE WHEN Result = -3
THEN Reason +' '+Subject
ELSE Result
END As FailedIn
FROM mytable
GROUP BY Name, Result
Try this
SELECT NAME, SCORE,
CASE WHEN SCORE = -3 THEN CONCAT(REASON, ' ' ,SUBJECT )
ELSE '0'
END as FAILEDIN FROM ScoreTable

Show 2 count in 1 result

I need to display a single result so that I can extract it.
This is my table named 'TRY'
id | type |
01 | A |
01 | D |
01 | A |
My query is like this:
select
lpad(id,2,'0')||
lpad(count(case when type = 'A' then 1 end),3,'0')||
lpad(count(case when type = 'D' then 1 end),3,'0')||
lpad(count(case when type in ('A','D') then 1 end),3,'0') then 1 end)
as results
from
TRY
group by
id
,type
I want the result to show like this 01002001003 but instead I got 2 result which are like this
01002000002 and 01000001001. I just want to combine the count result as one.
I think that the main thing that you need to consider is how the GROUP BY clause actually works, as you have actually grouped by id and type meaning that you'll never have a positive count for type A and type D on the same row as they are not grouped together.
In your example I have noticed the following and worked to these parameters:
You want to GROUP BY id (not GROUP BY id, type)
Your returned result is a concatenated string which consists of
the id (padded to 2 characters)
the number of Type A's (padded to 3 characters)
the number of type D (padded to 3 characters)
the total number of A's and D's combined. (padded to 3 characters)
You actually also want to be using the SUM function instead of COUNT so something along the lines of the following should work:
Oracle/PLSQL
SELECT
LPAD(id,2,'0')
|| LPAD(SUM(CASE WHEN type = 'A' THEN 1 ELSE 0 END),3,'0')
|| LPAD(SUM(CASE WHEN type = 'A' THEN 1 ELSE 0 END),3,'0')
|| LPAD(SUM(CASE WHEN type = 'A' OR type = 'D' THEN 1 ELSE 0 END),3,'0')
AS results
FROM
TRY
GROUP BY
id
On the unlikely off-chance you're actually using SQL Server or another Database engine the LPAD function will not actually work so using something along the lines of the following may work instead. (Also added in case some non ORACLE users have a similar quandary and it's what I used to resolve your issue)
SELECT
[results] =
RIGHT('00' + CONVERT(VARCHAR,[id]),2)
+ RIGHT('000' + CONVERT(VARCHAR,SUM(CASE WHEN [type] = 'A' THEN 1 ELSE 0 END)),3)
+ RIGHT('000' + CONVERT(VARCHAR,SUM(CASE WHEN [type] = 'D' THEN 1 ELSE 0 END)),3)
+ RIGHT('000' + CONVERT(VARCHAR,SUM(CASE WHEN [type] = 'A' OR type = 'D' THEN 1 ELSE 0 END)),3)
FROM
[TRY]
GROUP BY
[id]

How to select two rows into a single row output

The select statement looks like this right now
Here i got the output in 2 lines for the same stg_edi835_id ,I want to select the results in a single line for that stg_edi835_id.
Output should look like this
Can some please help me in doing this
Thanks in advance..
SELECT STG_EDI835_PLB_ID, STG_EDI835_ID, ADJUSTMENTREASONCODE1, ADJUSTMENTIDENTIFIER1, SUM(NTVE_ADJUSTMENTAMOUNT1_T1+NTVE_ADJUSTMENTAMOUNT1_T2) AS ADJUSTMENTAMOUNT1,
SUM(PTVE_ADJUSTMENTAMOUNT1_T1+PTVE_ADJUSTMENTAMOUNT1_T2) AS ADJUSTMENTAMOUNT2, ADJUSTMENTREASONCODE2, ADJUSTMENTIDENTIFIER2
FROM
(
SELECT T1.STG_EDI835_PLB_ID , T2.STG_EDI835_ID, T1.ADJUSTMENTREASONCODE1, T1.ADJUSTMENTIDENTIFIER1,
(CASE WHEN T1.ADJUSTMENTAMOUNT1 < 0 THEN T1.ADJUSTMENTAMOUNT1 ELSE 0 END) AS NTVE_ADJUSTMENTAMOUNT1_T1,
(CASE WHEN T2.ADJUSTMENTAMOUNT1 < 0 THEN T2.ADJUSTMENTAMOUNT1 ELSE 0 END) AS NTVE_ADJUSTMENTAMOUNT1_T2,
(CASE WHEN T1.ADJUSTMENTAMOUNT1 >= 0 THEN T1.ADJUSTMENTAMOUNT1 ELSE 0 END) AS PTVE_ADJUSTMENTAMOUNT1_T1,
(CASE WHEN T2.ADJUSTMENTAMOUNT1 >= 0 THEN T2.ADJUSTMENTAMOUNT1 ELSE 0 END) AS PTVE_ADJUSTMENTAMOUNT1_T2,
COALESCE(T2.ADJUSTMENTREASONCODE1, 'NULL') AS ADJUSTMENTREASONCODE2, COALESCE(T2.ADJUSTMENTIDENTIFIER1, NULL) AS ADJUSTMENTIDENTIFIER2
FROM TABLE1 AS T1
INNER JOIN TABLES T2
ON T2.STG_EDI835_ID = T1.STG_EDI835_ID
AND T2.STG_EDI835_PLB_ID = T1.STG_EDI835_PLB_ID
) A
GROUP BY STG_EDI835_PLB_ID, STG_EDI835_ID, ADJUSTMENTREASONCODE1, ADJUSTMENTIDENTIFIER1, ADJUSTMENTREASONCODE2, ADJUSTMENTIDENTIFIER2
Your question is somewhat incomplete (you should show your desired output), however, here is a sample of what you could do:
get rid of all unique values you don't need. (column 1, containing ID's, etc.)
Use aggregate functions on the rest.
Example:
Select
--column 1 removed
MAX(column2) as ID,
MAX(column3) as RefID,
--column 4 removed
--column 5 removed
--column 6 removed
SUM(column7) as Ad1,
--column 8 removed
--column 9 removed
SUM(column10) as Ad2
From
table
Try something like
WITH DATA As (
select 697 as Stg_EDI835_Id, -87.75 as AdjustmentAmount1 union
select 697, -4.64 union
select 612, -6.39 union
select 612, 60.75
)
select SUM(AdjustmentAmount1) AS AdjustmentAmount1, 0 AS adjustmentamount2 FROM DATA GROUP BY Stg_EDI835_Id HAVING SUM(AdjustmentAmount1) <= 0 UNION
select 0, SUM(AdjustmentAmount1)FROM DATA GROUP BY Stg_EDI835_Id HAVING SUM(AdjustmentAmount1) > 0
Output is
AdjustmentAmount1 | Adjustmentamount2
-92.39 | 0.00
0.00 | 54.36

having issues sorting alpha numeric chars

I am trying to sort one column which have alphanumeric letters
see my query below
SELECT d.number
FROM table name d, table_name 2 a WHERE d.case_id ='11-41'
AND d.ExhibitTypeId = TypeId AND d.ComplianceNo = '0' and
active = 1 and number is not null order by case
when ISNUMERIC(d.number) = 1 then right('0000000000'+d.number+'0',10)
else right('0000000000'+d.number,10)
end
This is the output
1
2
3
11
12
2A1
I want this output instead
1
2
2A1
3
11
12
Any help regarding this is greatly appreciated.
If(ISNUMERIC(LEFT(case,2)
BEGIN
order by case
END
else
BEGIN
order by LEFT(case,1), LEFT(case,2)
END
Assuming SQL Server this may work with some tweaks
SELECT
d.number
FROM
table name d,
table_name 2 a
WHERE
d.case_id ='11-41'
AND
d.ExhibitTypeId = TypeId
AND
d.ComplianceNo = '0'
and
active = 1
and number is not null
order by
Convert(int, LEFT(number, Case
When PATINDEX('%[^0-9]%', number) > 0 Then PATINDEX('%[^0-9]%', number) - 1
Else LEN(number)
End)
),
LEN(Number)