default value for column in SQL view - sql

I have an SQL view vith many columns.
ID (land parcel ID) ex : 7465-85-7468
Building (ID of a specific building if needed) ex : 102
Room (ID of a specific room if needed) ex : 0023
I have an ID for each row, but for most of the rows, there is not Building ID or Room ID
I'd like to fill the blank rows with '000' for building, and '0000' for Room.
I could Concat these fields in a fourth field (full ID)
It tried to get a default value with "ISNULL", but it didn't work.
For Now, I have somethins like this
ID / Building / Room / Full ID
7848-05-6956 / / / 7848-05-6956--
6985-26-7485 / 102 / 0000 / 6985-26-7485-102-0000
7236-12-0145 / / 0223 / 7236-12-0145--0223
I'd need this
ID / Building / Room / Full ID
7848-05-6956 / 000 / 0000 / 7848-05-6956-000-0000
6985-26-7485 / 102 / 0000 / 6985-26-7485-102-0000
7236-12-0145 / 000 / 0223 / 7236-12-0145-000-0223

If the field is not nullable, the data may be stored as empty strings rather than NULL's.
Try doing something like the following:
SELECT x.ID, x.Building, x.Room, ID + '-' + Building + '-' + Room AS [Full ID]
FROM (
SELECT
ID
, CASE WHEN ISNULL(Building, '') = '' THEN '000' ELSE Building END AS Building
, CASE WHEN ISNULL(Room, '') = '' THEN '0000' ELSE Room END AS Room
FROM MyTable ) x
This will handle both NULL and empty string and it will allow you to build Full ID without executing the CASE statements twice.

Related

Trying to Multiply a Case Statement to a Count

DECLARE #StartDate datetimeoffset,
#EndDate datetimeoffset
SET #StartDate = '2022-03-01 00:00:00.000 +07:00'
SET #EndDate = '2022-03-06 23:59:59.000 +07:00'
SELECT
Records.RecordID,
CONVERT(VARCHAR(10),Records.RecDate AT TIME ZONE 'SE Asia Standard Time',104) AS RecTime,
LocationStr, LocationName,
CONCAT(FirstName,' ',LastName) AS Username ,ProductCodeName,
CASE
WHEN AssetTypeName LIKE '%LTR'
THEN LEFT(AssetTypeName, LEN(AssetTypeName) - 3)
ELSE LEFT(AssetTypeName, LEN(AssetTypeName) - 2)
END * COUNT (ProductCodeName) AS 'SumProduct'
FROM
opendata.records
INNER JOIN
opendata.RecAssets ON Records.RecordId = RecAssets.RecordId
WHERE
(Records.ActionName = 'Fill')
AND (IsDeleted = '0')
AND (Records.RecDate BETWEEN #StartDate and #EndDate)
AND (LocationStr = '3031')
GROUP BY
Records.RecordId, Records.RecDate, LocationStr, LocationName,
CONCAT(FirstName,' ', LastName), ProductCodeName, AssetTypeName
ORDER BY
LocationStr ASC, RecTime ASC, ProductCodeName ASC
Tried to multiply the last to column on my Select statement but failed to do so. I get an error
Conversion failed when converting the ****** value '******' to data type ******.
Furthermore, I tried to convert the case statement to an int but also failed. How can I directly multiply it?
I'm guessing that you're using sql server seeing as it's not oracle and len() is not supported in mySQL or Postgres. You're code calls for an implicit conversion from a numerical value in a char type to a number, for example '123' to 123.
In the following example this doesn't present a problem the first time, but the second time there is a letter in the char value which cannot be converted and throws an error.
I am therefore thinking that you have values of AssetTypeName where there are letters other than in the last 2 characters for non-LTR values of elsewhere in the string for those ending in LTR.
create table test(
AssetTypeName varchar(10),
ProductCodeName int);
insert into test values
('123LTR',1),
('123LTR',1),
('123AB',1);
GO
3 rows affected
select
AssetTypeName,
CASE
WHEN AssetTypeName LIKE '%LTR'
THEN LEFT(AssetTypeName, LEN(AssetTypeName) - 3)
ELSE LEFT(AssetTypeName, LEN(AssetTypeName) - 2)
END * COUNT (ProductCodeName) AS 'SumProduct'
from test
group by AssetTypeName;
GO
AssetTypeName | SumProduct
:------------ | ---------:
123AB | 123
123LTR | 246
insert into test values ('123ABC',1);
GO
1 rows affected
select
AssetTypeName,
CASE
WHEN AssetTypeName LIKE '%LTR'
THEN LEFT(AssetTypeName, LEN(AssetTypeName) - 3)
ELSE LEFT(AssetTypeName, LEN(AssetTypeName) - 2)
END * COUNT (ProductCodeName) AS 'SumProduct'
from test
group by AssetTypeName;
GO
Msg 245 Level 16 State 1 Line 1
Conversion failed when converting the varchar value '123A' to data type int.
db<>fiddle here

How can I check the maximum value from a set of tables in SQL Server (if possible)?

We have a set of databases (80 in total). Every single one has a table called tblProfessions. The tables are not standardized. For example:
EDIT: all the databases are on the same server.
The DB1.dbo.tblProfessions is like:
intProfessionCode
strProfessionDescription
1
lawyer
2
dentist
...
...
30
doctor
And the DB72.dbo.tblProfessions is as follows:
intProfessionCode
strProfessionDescription
1
designer
2
butcher
...
...
80
chef
Suppose I ran a script from DBO1 to DBO72, and I found that the biggest table has 80 entries (in this case the DBO72 is the biggest one).
By my limited knowledge, all I know is to run the below script database by database, and write it down in a spreadsheet manually:
SELECT MAX(intProfessionCode) FROM [DB].dbo.tblProfessions;
Is there a script to run and loop through all the tblProfessions and get the one with the most entries? All I want is the biggest number found.
Thanks in advance.
You should be able to do something like this:
WITH dat
AS
(
SELECT 'db1' AS database_name, MAX(intProfessionCode) AS max_intProfessionCode
FROM DB1.dbo.tblProfessions
UNION ALL
...
UNION ALL
SELECT 'db72' AS database_name, MAX(intProfessionCode) AS max_intProfessionCode
FROM DB72.dbo.tblProfessions
)
SELECT dat.db, dat.max_intProfessionCode
FROM dat
INNER JOIN (SELECT MAX(max_intProfessionCode) AS max_intProfessionCode_overall
FROM dat) y
ON dat.max_intProfessionCode = y.max_intProfessionCode_overall
For situations like this, I usually query the catalog to write the above script rather than typing it out:
WITH
dat AS
(
SELECT STRING_AGG('SELECT ''' + QUOTENAME(s.name) + ''' AS db,
MAX(intProfessionCode) AS max_intProfessionCode
FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME('dbo') + '.' + QUOTENAME('tblProfessions') + '
UNION ALL',' ') AS s
FROM sys.databases s
WHERE s.name LIKE 'DB%' --EDIT APPROPRIATELY
)
SELECT 'WITH dat
AS
(' + SUBSTRING(s,1,LEN(s) - LEN(' UNION ALL')) + ')
SELECT dat.db, dat.max_intProfessionCode
FROM dat
INNER JOIN (SELECT MAX(max_intProfessionCode) AS max_intProfessionCode_overall
FROM dat) y
ON dat.max_intProfessionCode = y.max_intProfessionCode_overall' AS scrpt
FROM dat;
Make sure the above is only returning data for the appropriate databases by editing the WHERE clause in the CTE, then copy the output, paste elsewhere and run it to get your results.

Issue in Selection with CHARINDEX and SUBSTRING

I have 2 questions here.
I have a column 'Campaign' with these entries. My objective is to extract the Cost part from the string and create a new column Cost in my table
29693214 - Live -JUTL Phase 2 Creator Stories Trailer * 7.12 - 7.25 * Video Views * $28,169.01 * BG - Mob
89695072 - Live -WUTL Retargeting JG * 7.16 - 7.31 * Link Clicks * $23,474.18 * KG - Mob
I tried select SUBSTRING(Campaign,CHARINDEX('$',Campaign) +1,???) .I am unable to figure out the '???' part. I want to start with the index next to '$' and continue till the '*' symbol to capture the cost.
While creating a new column I follow these steps
Alter table T ADD NewColumn varchar(100)
then I do this
Update T SET NewColumn = 'Say I want that cost part from the above question here'
Is there any efficient way to do this in single shot?
I think apply makes these operations a bit simpler:
select left(v1.str1, charindex(' ', v1.str1))
from (values ('29693214 - Live -JUTL Phase 2 Creator Stories Trailer * 7.12 - 7.25 * Video Views * $28,169.01 * BG - Mob')) v(str) cross apply
(values (stuff(str, 1, charindex('$', str), ''))) v1(str1);
This can readily be incorporated into an update:
Update t
set newcolumn = left(v.str1, charindex(' ', v.str1))
from t cross apply
(values (stuff(t.str, 1, charindex('$', str), ''))) v(str1)
DDL for testing query:
declare #tbl table(Campaign varchar(200));
insert into #tbl values
('29693214 - Live -JUTL Phase 2 Creator Stories Trailer * 7.12 - 7.25 * Video Views * $28,169.01 * BG - Mob'),
('189695072 - Live -WUTL Retargeting JG * 7.16 - 7.31 * Link Clicks * $23,474.18 * KG - Mob');
If the cost is always separated by a asterisk * from other part of the string, you could use below query:
select trim(substring(Campaign, dollarIndex + 1, asteriskIndex - dollarIndex - 1)) from (
select Campaign, charindex('$', Campaign) dollarIndex,
charindex('*', Campaign, charindex('$', Campaign)) asteriskIndex
from #tbl
) a
To use it in update statement, you could use the same query, but we need to transform above into single query:
update #tbl set Campaign = trim(substring(Campaign, charindex('$', Campaign) + 1, charindex('*', Campaign, charindex('$', Campaign)) - charindex('$', Campaign) - 1))
Note: consider if it's worthy keeping data that you already have (redundancy). If it can be always be parsed from your column in the same way you could use view for this task.
On the other hand it might be qiute expensive to query such data and might be bad for performance.

Long arithmetic with SQL SELECT statement

The basic idea is I have 3 separate SELECT statements that output a number. I need a percentage from those numbers. So the problem would look like this:
(a.count_one + b.count_two) -
(b.count_two + c.count_three) / (a.count_one + b.Count_two) * 100
When I do the code found below I only get the output of the first (a.count_one + b.count_two). BUT if I comment out the third portion which is / (a.count_one + b.count_two) I successfully get the correct solution from (a.count_one + b.count_two) – (b.count_two + c.count_three).
So it appears, doing math of two statements is great, but when I throw in a third statement it pukes and only wants to show the solution of the first problem (a.count_one + b.count_two), but does not even try to calculate the solution for (a.count_one + b.count_two) – (b.count_two + c.count_three) anymore. I'm a bit stumped why.
Select
(a.Count_one + b.Count_two) -
(b.Count_two + c.Count_three) / (a.Count_one + b.Count_two) * 100
as 'Final_Percentage'
from
(
select COUNT(v_Summary.ResourceID) AS Count_one
From [DB1].[dbo].[v_Summary]
) a,
(
select count([CN]) as Count_two
From [DB2].[dbo].[Computers]
WHERE cn NOT IN (SELECT name0 FROM [DB1].[dbo].[v_system] where v_system.Client0 = '1')
) b,
(
select COUNT(v_Summary.ResourceID) AS Count_three
From [DB1].[dbo].[v_Summary]
Where Description like '%/Fail'
) c
And to give additional information. The math problem with numbers:
(54558 + 373) – (373 + 117) / (54558 + 373) * 100
Or further solved:
(54931) - (490) / 55304 * 100 = 98.44%
COUNT function returns int. When you divide two int values the result is again int in SQL Server. So, 490 / 55304 is 0. Then 0 * 100 is 0 again.
Cast the values to a suitable type, like float.
By the way,
(54931) - (490) / 55304 * 100
is not equal to ~98.44, it is equal to ~54930.11399
You need parentheses to get the result you expect:
((54931) - (490)) / 55304 * 100
is equal to ~98.43953421
So, the final query should look like this:
Select
((a.Count_one + b.Count_two) - (b.Count_two + c.Count_three))
/ (a.Count_one + b.Count_two) * 100
as 'Final_Percentage'
from
(
select CAST(COUNT(v_Summary.ResourceID) AS float) AS Count_one
From [DB1].[dbo].[v_Summary]
) a,
(
select CAST(count([CN]) AS float) as Count_two
From [DB2].[dbo].[Computers]
WHERE cn NOT IN (SELECT name0 FROM [DB1].[dbo].[v_system] where v_system.Client0 = '1')
) b,
(
select CAST(COUNT(v_Summary.ResourceID) AS float) AS Count_three
From [DB1].[dbo].[v_Summary]
Where Description like '%/Fail'
) c
You should also get the right result by saying
Select
100.*(a.Count_one - c.Count_three) / (a.Count_one + b.Count_two)
as 'Final_Percentage'
from ... -- unchanged subqueries, as supplied in your question
By moving the *100. right to the front you implicitly convert the first product to float and the type then stays that way for the rest of the calculation. Also, you might have noticed, I simplified the formula, since b.Count_two gets subtracted from itself, so you can leave it out altogether. I have not tested this but I am pretty sure it will work.

Return all results of substring with in string

I have some odd data in a vendor database but need to be able to extract multiple different parameters from one field in the db.
So from this example i would like to pull out all items that fall between (" % ")
Between quotes is a string, disregard that it looks like code:
"Func_GetParameterLatestValue("IBW Patient Height RT Assess") kHeight =Func_GetParameterLatestValue("Height For IBW Vent Misc") If (kSex) = "" Then
Return_Value =NULL Else If kHeight > 0 Then If kSex=1 Then Return_Value= Round(((kHeight - 152.4)*.91)+50,0) Else
Return_Value= Round(((kHeight - 152.4)*.91)+45.5,0) End IF Else Return_Value = NULL End IF End IF ' Return_Value = kHeight '("IBW Patient Height RT Assess")"
so the return values would be:
IBW Patient Height RT Assess,
Height For IBW Vent Misc,
IBW Patient Height RT Assess
Im open to any suggestions to try and make this work. Ideally i would like to be able to slam the results in a subquery as well to make sure that they exist on another table.
This query currently returns the first instance
select vbs.Name,
SUBSTRING(sd.FormulaDetails,
CHARINDEX('("', sd.FormulaDetails)+2,(CHARINDEX('")',sd.FormulaDetails) - CHARINDEX('("', sd.FormulaDetails))-2)
from StatementDefinitions sd, MvVBScript vbs
where sd.ScriptID = vbs.ID
You can do this recursively with a WITH statement. Here's a shot at it. Change varchar(max) to whatever the data type of your FormulaDetails column is. In case you want it, this query returns the ScriptID and numbers the position of the chunk it finds (so 'Height For IBW Vent Misc' would be occurrence 2)
with Chunks(id,occurrence,position,token,remainder) as (
select
ScriptID,
cast(0 as int),
charindex(#token,FormulaDetails),
cast('' as varchar(max)),
substring(c,charindex(#token,FormulaDetails)+1,len(FormulaDetails))
from StatementDefinitions
where FormulaDetails like '%'+#token+'%'
union all
select
id,
occurrence+1,
charindex(#token,remainder)+position,
cast(substring(remainder,1,charindex(#token,remainder)-1) as varchar(max)),
substring(remainder,charindex(#token,remainder)+1,len(remainder))
from Chunks
where remainder like '%'+#token+'%'
)
select id, occurrence, token from Chunks
where occurrence > 0
order by id;