Convert and sum variable a, grouping by variable b - sql

I would like to convert the variable ar66 from nvarchar to numeric and sum it for the variable ar5.
I create the following code, but it does not work:
select top(10) ar5, (
select
case
when isnumeric(q1.ar66) = 1 then
cast(q1.ar66 AS numeric)
else
NULL
end
AS 'ar66_numeric'
from rmb_loan q1)
from rmb_loan q2
group by q2.ar5
Do you have any suggestion to solve the problem?

Does this do what you want?
select top (10) ar5, sum(try_convert(numeric(38, 6), q1.ar66))
from rmb_loan q2
group by q2.ar5;
When using select top you should normally have an order by clause.

Related

Return 1 if value is 0 without CASE statement

I'm trying to find a tidier way of doing the below query so that I'm not duplicating my code.
SELECT CASE WHEN <COMPLICATED CODE THAT RETURNS A SINGLE INT> = 0
THEN 1
ELSE <COMPLICATED CODE THAT RETURNS A SINGLE INT> END
Ideally, I would like something like this using an existing function rather than creating my own:
SELECT ISVALUE(COMPLICATED CODE THAT RETURNS A SINGLE INT,0,1)
You can use apply:
SELECT (CASE WHEN v.val = 0 THEN 1 ELSE v.val END)
FROM . . . CROSS APPLY
(VALUES (<COMPLICATED CODE THAT RETURNS A SINGLE INT>)) v(val);
You could also do a series of functions:
select coalesce(nullif(<COMPLICATED CODE THAT RETURNS A SINGLE INT>, 0), 1)
However, I think apply is clearer. In addition the above will turn NULL values into 1 as well as 0.
You can use a CTE (or a subquery) as
WITH CTE AS
(
SELECT <COMPLICATED CODE THAT RETURNS A SINGLE INT> AS Value
FROM ...
)
SELECT CASE WHEN Value = 0 THEN 1 ELSE Value END
FROM CTE
This way you write the complicated code just once, and then use just the Value column.
You can use IIF:
SELECT IIF(1 = 1, 'true', 'false')
https://learn.microsoft.com/en-us/sql/t-sql/functions/logical-functions-iif-transact-sql
use a sub query, then you can figure out a mathematical formula that acts to give the values you desire, that way you can eliminate actual boolean logic and replace with mathematical functions
an example is
SELECT *,(1 - ceiling(cos(atan(abs(cast(x as float)))) -
floor(cos(atan(abs(cast(x as float))))))) +
x * ceiling(cos(atan(abs(cast(x as float)))) -
floor(cos(atan(abs(cast(x as float)))))) as Computed
FROM
( select 0 as x union SELECT 1 X UNION SELECT -.123 UNION SELECT 9.1 UNION SELECT 67000 union select -1) OQ

SQL query to select with Range condition in source table

Have a scenario to select the value from table where range condition is present in source table.
Like,
TableA
ID value condition
1 20 A-M
2 50 N-Z
Select value from TableA where condition = 'C%'
--want to select TableA value from TableB by passing person name starts with like,
-- Here C is item name starts with
-- Should compare with range (A-M) and return first row.
-- Condition column is varchar(3)
I have seen the solution on other way where range can be compared with input value, but here the range is present in the source table. Please help.
If I have understood what you are after correctly you can use
SELECT TOP 1 B.*
FROM TableB B
WHERE B.Name LIKE (SELECT CONCAT('[',condition,']%') FROM TableA WHERE ID =1)
ORDER BY B.Id
If I understand correctly, you should be structuring TableA as:
ID value Lower Upper
1 20 A M
2 50 N Z
Then you want:
select a.*
from tableA a
where left(#name, 1) between a.lower and a.upper;
You can get this to work with your format, by doing:
select a.*
from tableA a
where left(#name, 1) between left(a.condition) and right(a.condition);
But I don't recommend that. Better to store the condition in two columns.
I would use QUOTENAME() function as
SELECT *
FROM TableA
WHERE #Condition LIKE QUOTENAME(Condition);
This will be as
WHERE 'C' LIKE [A-M] --return True
Demo1
Demo2
Always you should try to add data and DDL for setup correctly the test scenario, here my proposed solution:
DECLARE #SourceA AS TABLE
(
ID INT,
Value INT,
Condition VARCHAR(100)
);
INSERT INTO #SourceA ( ID ,
Value ,
Condition
)
VALUES ( 1 , -- ID - int
110 , -- Value - int
'A-M' -- Condition - varchar(100)
),(2,250,'N-Z')
DECLARE #Alphabet VARCHAR(200)='A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z';
; WITH MyCTE AS
(
SELECT ID,Value,Condition, SUBSTRING(#Alphabet, PATINDEX('%'+ LEFT(Condition,1) + '%' ,#Alphabet),(LEN(#Alphabet)-PATINDEX('%'+ RIGHT(Condition,1) + '%' ,#Alphabet))+1) AS FormattedCondition
FROM #SourceA
)
SELECT * FROM MyCTE
WHERE MyCTE.FormattedCondition LIKE '%C%'

Why this sql will cause type conversion error?

WITH tb_testl AS (
SELECT 1 AS id ,'hehe' AS value
UNION ALL
SELECT 1 AS id, '1' AS value
UNION ALL
SELECT 2 AS id, '2' AS value
UNION ALL
SELECT 2 AS id, '2' AS value
), tb_test2 AS (
SELECT CONVERT(INT , value) AS value FROM tb_testl WHERE id = 2
)
SELECT * FROM tb_test2 WHERE value = 2;
this sql will cause error
Conversion failed when converting the varchar value 'hehe' to data
type int.
but the table tb_test2 dosen't have the value 'hehe' which is in the anthor table tb_test1. And I found that this sql will work well if I don't append the statement WHERE value = 2; .I've tried ISNUMBERIC function but it didn't work.
version:mssql2008 R2
With respect to the why this occurs:
There is a Logical Processing Order, which describes the order in which clauses are evaluated. The order is:
FROM
ON
JOIN
WHERE
GROUP BY
WITH CUBE or WITH ROLLUP
HAVING
SELECT
DISTINCT
ORDER BY
TOP
You can also see the processing order when you SET SHOWPLAN_ALL ON. For this query, the processing is as follows:
Constant scan - this is the FROM clause, which consists of hard coded values, hence the constants.
Filter - this is the WHERE clause. While it looks like there are two where clauses (WHERE id = 2 and WHERE value = 2). SQL Server sees this differently, it considers a single WHERE clause: WHERE CONVERT(INT , value) = 2 AND id = 2.
Compute scaler. This is the CONVERT function in the select.
Because both WHERE clauses are executed simultaneously, the hehe value is not filtered out of the CONVERT scope.
Effectively, the query is simplified to something like:
SELECT CONVERT(INT, tb_testl.value) AS Cvalue
FROM (
SELECT 1 AS id
, 'hehe' AS value
UNION ALL
SELECT 1 AS id
, '1' AS value
UNION ALL
SELECT 2 AS id
, '2' AS value
UNION ALL
SELECT 2 AS id
, '2' AS value
) tb_testl
WHERE CONVERT(INT, tb_testl.value) = 2
AND tb_testl.id = 2
Which should clarify why the error occurs.
With SQL, you cannot read code in the same way as imperative languages like C. Lines of SQL code are not necessarily (mostly not at all, in fact) executed in the same order it is written in. In this case, it's an error to think the inner where is executed before the outer where.
SQL Server does not guarantee the order of processing of statements (with one exception below). That is, there is no guarantee that WHERE filtering happens before the SELECT. Or that one CTE is evaluated before another. This is considered an advantage because it allows SQL Server to rearrange the processing to optimize performance (although I consider the issue that you are seeing a bug).
Obviously, the problem is in this part of the code:
tb_test2 AS (
SELECT CONVERT(INT, value) AS value
FROM tb_testl
WHERE id = 2
)
(Well, actually, it is where tb_test2 is referenced.)
What is happening is that SQL Server pushes the CONVERT() to where the values are being read, so the conversion is attempted before the WHERE clause is processed. Hence, the error.
In SQL Server 2012+, you can easily solve this using TRY_CNVERT():
tb_test2 AS (
SELECT TRY_CONVERT(INT, value) AS value
FROM tb_testl
WHERE id = 2
)
However, that doesn't work in SQL Server 2008. You can use the fact that CASE does have some guarantees on the order of processing:
tb_test2 AS (
SELECT (CASE WHEN value NOT LIKE '%[^0-9]%' THEN CONVERT(INT, value)
END) AS value
FROM tb_testl
WHERE id = 2
)
error caused by this part of statement
), tb_test2 AS (
SELECT CONVERT(INT , value) AS value FROM tb_testl WHERE id = 2
value has type of varchar and 'hehe' value cannot be converted to integer
WITH tb_testl AS (
SELECT 1 AS id ,'hehe' AS value
UPDATE: sql try convert all value(s) to integer in you statement. to avoid error rewrite statement as
WITH tb_testl AS (
SELECT 1 AS id ,'hehe' AS value
UNION ALL SELECT 1 AS id, '1' AS value
UNION ALL SELECT 2 AS id, '2' AS value
UNION ALL SELECT 2 AS id, '2' AS value
), tb_test2 AS (
SELECT value AS value FROM tb_testl WHERE id = 2
),
tb_test3 AS (
SELECT cast(value as int) AS value FROM tb_test2
)
SELECT * FROM tb_test3

Query division returns 0

I am working on a query that devide 2 columns, I tried CAST and CONVERT but still returns 0. Will apperciate your help
SELECT a.Disposition,a.[Disposition Reason Breakdown],a.CSP,b.Total FROM
(
SELECT a.[Disposition],a.[Disposition Reason Breakdown],a.[CSP] FROM
(
SELECT [Disposition],[Disposition Reason Breakdown],COUNT(*) as CSP FROM [dbo].[Disposition]
WHERE [Disposition] <> 'Interested'
GROUP BY [Disposition],[Disposition Reason Breakdown]
) a
)a
INNER JOIN
(
SELECT a.Disposition,SUM(a.CSP) as Total FROM
(
SELECT [Disposition],[Disposition Reason Breakdown],COUNT(*) as CSP FROM [dbo].[Disposition]
WHERE [Disposition] <> 'Interested'
GROUP BY [Disposition],[Disposition Reason Breakdown]
)a
GROUP BY a.Disposition
)b ON a.Disposition = b.Disposition
I am using sql
I solved it, it turns out that I just used the wrong data type which in my case is decimal I should've thought of REAL here is the final query a.CSP/CAST(b.Total as REAL)

SELECT with not equal condition

How to i display the invoicenumber only if the extended price is not equal to subtotal?
Following query is fail to run and error group function is not allowed here
SELECT a.INVOICENUMBER,SUM(a.EXTENDEDPRICE),SUM(a.SUBTOTAL)
FROM CUSTOMERORDERHISTORYVIEW a
WHERE EXISTS
(SELECT a1.INVOICENUMBER FROM CUSTOMERORDERHISTORYVIEW a1 WHERE
a.INVOICENUMBER=a1.INVOICENUMBER AND SUM(a1.EXTENDEDPRICE) <> SUM(a1.SUBTOTAL))
GROUP BY a.INVOICENUMBER;
You are looking for the having clause:
SELECT a.INVOICENUMBER, SUM(a.EXTENDEDPRICE), SUM(a.SUBTOTAL)
FROM CUSTOMERORDERHISTORYVIEW a
GROUP BY a.INVOICENUMBER;
HAVING SUM(a.EXTENDEDPRICE) <> SUM(a.SUBTOTAL);