SQL LIKE is only working With Full Name - sql

In one of my sp I have following lines of code
select distinct (a.itemid), a.itemcode, v.itemdescription
from aitem a
INNER JOIN vwitemdescription v ON a.itemID = v.itemID
WHERE a.active=1
-----------------------------------------
AND (#ItemDesc like '%'+ a.itemdescription +'%')
-----------------------------------------
If I give #ItemDesc value in full description, I get values and if I give #ItemDesc value in half description I get nothing in return.
For Example :
If I giv
#ItemDesc = 'Cow Dung - '
I get result as
---------------------------------------
|itemid | itemcode | itemdescription |
--------------------------------------
| 63 | 40-17005 | Cow Dung - |
---------------------------------------
And even if I cut the string as #ItemDesc = 'Cow Dung' I get the same results,
But if I cut it into #ItemDesc = 'Cow' or only to single character I don't get any results.
I want to load the item even if I enter only a single charecter in it.
Is there anything wrong with my code? How to get it right?

You need to switch the items in your LIKE expression:
AND a.itemdescription LIKE '%' + #ItemDesc + '%'
Using this logic, any substring of the itemdescription would match. For example the following is a true condition:
AND `Cow Dung - ` LIKE '%Cow%'
Here is the full query:
SELECT DISTINCT
a.itemid, a.itemcode, v.itemdescription
FROM aitem a
INNER JOIN vwitemdescription v
ON a.itemID = v.itemID
WHERE
a.active = 1 AND
a.itemdescription LIKE '%' + #ItemDesc + '%';

Comparison variable should be always at the right side of the statement. Your new query should be as below.
select distinct (a.itemid), a.itemcode, v.itemdescription
from aitem a
INNER JOIN vwitemdescription v ON a.itemID = v.itemID
WHERE a.active=1
--changed condition start
AND (a.itemdescription like '%'+ #ItemDesc +'%')
--changed condition end

Related

SQL join two tables by modifying on columns

I have 3 tables on PostgreSQL:
SPENDINGS:
store |spending
-----------+---------
0000700551 | $75
STORE:
store | zip_code
-------+---------
700551 | XXP PDD
CUSTOMER:
id | zip_code
----+----------
002 | XXPPDD
I would love to join these tables like this:
right(SPENDIGNS.store, 6) = STORE.store and
trim(STORE.zip_code) = CUSTOMER.zip_code.
How can I do that could you help me out please?
trim(store.zip_code) is not good for the job because the whitespace is within the zip code text. Use replace(store.zip_code, ' ', '') instead. right(spendings.store, 6) does not seem safe to me too. Better use ltrim(spendings.store, '0') to remove leading zeroes. SQL Fiddle
select *
from spendings sp
join store st on ltrim(sp.store, '0') = st.store
join customer cu on cu.zip_code = replace(st.zip_code, ' ', '');
BTW your data design does need improvement.
try something as follows (you can use what ever join you would like to in place of inner)
select spendings.spending, store.store,customer.zipcode
from spendings inner join store on right(SPENDIGNS.store, 6) = STORE.store
inner join customer on trim(STORE.zip_code) = CUSTOMER.zip_code

Use 'Stuff' variable in WHERE clause

So here is the query code we are using:
SELECT
CONVERT(DATE, Nominations.Nomination_Date_Created) AS Nomination_Date_Created,
Nominations.Nomination_Status,
(CASE
WHEN MIN(EPORT.dbo.FDA_Divisions.division_name) = MAX(EPORT.dbo.FDA_Divisions.division_name)
THEN MIN(EPORT.dbo.FDA_Divisions.division_name)
ELSE 'Multiple Divisions'
END) AS Employee_Division,
Nominations.Nomination_Awarded_For,
Nominations.Nomination_Awarded_Other,
Nom.First_Name + ' ' + Nom.Last_Name AS Nominator_Name,
Nominations.Nomination_Group_UUID,
Nominations.Nomination_Group_Name,
Nominations.Nomination_Group_Time_off_Sum,
Nominations.Nomination_Group_Cash_Sum,
Nominations.Nomination_Type,
Nominations.Nomination_Identifier, Nominations.Nomination_Employee_UUID,
Nominations.Nomination_Nominator_ID, Nominations.Nomination_NOAC,
STUFF((SELECT ', ' + NOMGroup.division_name
FROM vw_group_nomination_divisions NOMGroup
WHERE NOMGroup.Nomination_Group_UUID = Nominations.Nomination_Group_UUID
FOR XML PATH('')), 1, 1, '') divList
FROM
Nominations
INNER JOIN
ePort.dbo.Employees AS Employees_1 ON Employees_1.CapHR_ID = Nominations.Nomination_Employee_CapHR_ID
LEFT OUTER JOIN
ePort.dbo.FDA_Offices ON Employees_1.office_id = ePort.dbo.FDA_Offices.office_id
LEFT OUTER JOIN
ePort.dbo.FDA_Centers ON Employees_1.center_ID = ePort.dbo.FDA_Centers.Center_ID
LEFT OUTER JOIN
ePort.dbo.FDA_Divisions ON Employees_1.division_id = ePort.dbo.FDA_Divisions.division_ID
LEFT OUTER JOIN
ePort.dbo.Employees AS Nom ON Nominations.Nomination_Nominator_ID = Nom.CapHR_ID
LEFT OUTER JOIN
ePort.dbo.Employees AS NomAppRTO ON Nominations.Nomination_Approving_Officer_NED_ID = NomAppRTO.CapHR_ID
GROUP BY
CONVERT(DATE, Nominations.Nomination_Date_Created),
Nominations.Nomination_Awarded_For, Nominations.Nomination_Status,
Nominations.Nomination_Awarded_Other,
Nom.First_Name + ' ' + Nom.Last_Name,
Nominations.Nomination_Type, Nominations.Nomination_Group_UUID,
Nominations.Nomination_Group_Name,
Nominations.Nomination_Group_Time_off_Sum,
Nominations.Nomination_Group_Cash_Sum,
Nominations.Nomination_Identifier, Nominations.Nomination_Type,
Nominations.Nomination_Employee_UUID,
Nominations.Nomination_Nominator_ID, Nominations.Nomination_NOAC
HAVING
(Nominations.Nomination_Type = 'Group')
AND (YEAR(CONVERT(DATE, Nominations.Nomination_Date_Created)) IN ('2020'))
ORDER BY
Nomination_Date_Created DESC, Nominations.Nomination_Group_UUID
Output:
| Id | divList |
+--------------------------------------+-------------------+
| 3462BF9B-5056-9C58-994BFFC6A38E7368 | DLR, DTD, OHCM |
| 3B8202C2-5056-9C58-99C591AA86B3A1C9 | OHCM |
| CB5A722C-5056-9C58-9983C1F6C66C0AD7 | DTD, STMD |
And the output is how we need it, however, we need to be able to search it and we cannot get that working. So how does one reference the column 'Name' that the Stuff function creates in the WHERE clause of the query?
We need to do a search within the HAVING OR WHERE clause for a value within the 'divList' column if possible. Such as divList IN ('OHCM').
Anytime I reference 'divList', I get the error:
Invalid column name 'divList'.
This would filter the results to records 1 and 2.
I hope that better explains it.
You don't want the string. Use more basic logic instead:
having sum(case when division_name = 'ccc' then 1 else 0 end) > 0
How is your temp table associated with the view. You need to join your temp table with the nominations view.
SELECT ID,
STUFF((SELECT ', ' + NOMGroup.division_name
FROM vw_group_nomination_divisions NOMGroup
WHERE NOMGroup.Nomination_Group_UUID = nom.Nomination_Group_UUID
FOR XML PATH('')), 1, 1, '') Name
FROM temp1
JOIN vw_group_nomination_divisions nom ON temp1.ID = nom.ID
WHERE Nominations.[Name] = 'ccc'
GROUP by ID

how to use LIKE instead of IN with multiple values?

I want to replace In with Like to make the query work.
SELECT
1 AS coddit, COD_CAT AS cam_cod, DES_CAT AS cam_desc,
LIVELLO_CAT AS livello, COD_CAT_PADRE AS cat_padre,
COD_L1, COD_L2, COD_L3, COD_L4, COD_L5, COD_L6
FROM
dbo.CLASS_ART
WHERE
1=1
AND TIPO_CLASS = 16 --B2B
AND LIVELLO_CAT = '0'
AND COD_CAT IN (SELECT DISTINCT CAT_MERCE.COD_CAT
FROM ART_LIST_PREZZI
INNER JOIN ART_ANA ON ART_LIST_PREZZI.COD_ART = ART_ANA.COD_ART
INNER JOIN CAT_MERCE ON ART_ANA.COD_CAT = CAT_MERCE.COD_CAT
AND ART_LIST_PREZZI.COD_LIST = 'EXPORT_002')
The comparison I would like to do with LIKE otherwise the query doesn't work well
the subquery returns more than one value and it is correct but if I use Like instead of IN I have this error message:
Query return more than 1 values
Using LIKE against a subquery that returns multiple records won't work. A solution would be to turn the IN condition to an EXISTS condition, like:
and exists (
select 1
from ART_LIST_PREZZI
inner join ART_ANA
on ART_LIST_PREZZI.COD_ART = ART_ANA.COD_ART
inner join CAT_MERCE
on ART_ANA.COD_CAT = CAT_MERCE.COD_CAT
and ART_LIST_PREZZI.COD_LIST = 'EXPORT_002'
where COD_CAT like '%' + CAT_MERCE.COD_CAT + '%'
)
Like has to be compared to a single string, so you need to set all your ids on a single string. You can do that using the for xml clause.
(SELECT DISTINCT CAST(CAT_MERCE.COD_CAT AS VARCHAR(32))
FROM ART_LIST_PREZZI
INNER JOIN ART_ANA ON ART_LIST_PREZZI.COD_ART = ART_ANA.COD_ART
INNER JOIN CAT_MERCE ON ART_ANA.COD_CAT = CAT_MERCE.COD_CAT
AND ART_LIST_PREZZI.COD_LIST = 'EXPORT_002'
FOR XML PATH(''))
Now I would delimite your ids by commas, so you don't find false positives, and compare it using like.
AND
(SELECT DISTINCT ',' + CAST(CAT_MERCE.COD_CAT AS VARCHAR(32)) + ','
FROM ART_LIST_PREZZI
INNER JOIN ART_ANA ON ART_LIST_PREZZI.COD_ART = ART_ANA.COD_ART
INNER JOIN CAT_MERCE ON ART_ANA.COD_CAT = CAT_MERCE.COD_CAT
AND ART_LIST_PREZZI.COD_LIST = 'EXPORT_002'
FOR XML PATH('')) LIKE '%,' + COD_CAT + ',%'
This would work, and you would have changed your IN operator with a LIKE operator, but I don't see the point of it, its performance would be worse than your original query.
Use EXISTS:
EXISTS (SELECT 1
FROM ART_LIST_PREZZI LP JOIN
ART_ANA A
ON LP.COD_ART = A.COD_ART JOIN
CAT_MERCE M
ON A.COD_CAT = M.COD_CAT AND
LP.COD_LIST = 'EXPORT_002' AND
CLASS_ART.COD_CAT LIKE M.COD_CAT
)
I assume that the logic you actually want uses wildcards:
CLASS_ART.COD_CAT LIKE CONCAT('%', M.COD_CAT, '%')
If so, it suggests an issue with the data model. Why would two columns with the same name (COD_CAT) need to be joined using LIKE instead of =.

SQL Group by on outer reference after 2 inner joins

My sql query is not working as intended, in its current form it will return results, but some of them on the second column are duplicated, or in other words, some the computer names followed by the drive letter show twice.
The query is this:
(select Distinct 'ServerDrive' as storageType, cast(assetname as
varchar)+ '\ ' +cast(caption as varchar) as storagePath,((rqDiskdrivesHist.
[size]-rqDiskdrivesHist.[freespace])/1024/1024) as usedMB,(rqDiskdrivesHist.
[size]/1024/1024) as sizeMB from lansweeperdb.dbo.tblAssets
inner join rqDiskdrivesHist
on lansweeperdb.dbo.tblAssets.AssetID=rqDiskdrivesHist.AssetID
where drivetype=3
and lansweeperdb.dbo.tblAssets.AssetName in
(select distinct entitypath from rqcentities
inner join rqcustomer
on rqcentities.customerID=rqcustomer.customerID
where customername like '%ak 26%' and entityType='computer'
and not (
(AssetName like 'WFP3675' and caption like 'D:')
or
(AssetName like 'WFP3675' and caption like 'E:')
or
(AssetName like 'WFP3675' and caption like 'F:')
or
(AssetName like '%00500%')
)
))
If I try to group by at the end. with:
GROUP BY cast(assetname as varchar)+'\'+cast(caption as varchar)
I will get the "Each GROUP BY expression must contain at least one column that is not an outer reference.
" error.
Edit: These are 2 rows from the results which are duplicated.
You need to group on the alias instead as you did not expose those fields in the inner query.
SELECT
storageType,
storagePath,
MaxMB = MAX(usedMB),
MinMB = MIN(usedMB),
AvgMB = AVG(usedMB)
FROM
(
select 'ServerDrive' as storageType,
cast(assetname as varchar)+ '\ ' +cast(caption as varchar) as storagePath,
((rqDiskdrivesHist.[size]-rqDiskdrivesHist.[freespace])/1024/1024) as usedMB,
(rqDiskdrivesHist.[size]/1024/1024) as sizeMB
from
lansweeperdb.dbo.tblAssets
inner join rqDiskdrivesHist on lansweeperdb.dbo.tblAssets.AssetID=rqDiskdrivesHist.AssetID
where
drivetype=3
and lansweeperdb.dbo.tblAssets.AssetName in
(
select distinct entitypath
from rqcentities
inner join rqcustomer on rqcentities.customerID=rqcustomer.customerID
where customername like '%ak 26%' and entityType='computer'
and not (
(AssetName like 'WFP3675' and caption like 'D:')
or
(AssetName like 'WFP3675' and caption like 'E:')
or
(AssetName like 'WFP3675' and caption like 'F:')
or
(AssetName like '%00500%')
)
)
) AS X
GROUP BY
storagePath,
storageType

How to join two table with partial match

I have two table with the following data:
TableA.name
R4.23-Core-2
R4.23-Core-2
LA#213 CGHPBXsw01 127.213 0024-737e-e341
LA#252 CGHRack1sw01 127.252 0022-57ab-d781
SOC-01A-SW01
to - R4-DISTR-9512
to-R2-DISTR-5900-1
to-R3.25-EDGE
TableB.caption
R4.23-Core-2.ehd.ca
R4.23-Core-2.nhd.ca
CGHPBXsw01
CGHRack1sw01
SOC-01A-SW01
R4-DISTR-9512
R2-DISTR-5900-1.phsnc.
R3.25-EDGE.phsne.edjc.ca
I've tried using the following join statement but it doesn't seem to work for any row with a . in it.
dbo.TableA.Name
INNER JOIN dbo.TableB.Caption
ON dbo.TableA.Name LIKE '%' + dbo.TableB.Caption + '%'
I also try using replace function, which work but there are too much variant to include with replace.
I could try using the RIGHT or LEFT function to normalize the data but for row that doesn't have '.' it would throw an error. And I don't know how to skip row that doesn't have '.'
What is the most efficient way to join these two table?
In some situations in your example the caption is longer, and other times the name is longer, if you wanted to join on any value where name is in the caption or caption is in the name you could use:
dbo.TableA.Name
INNER JOIN dbo.TableB.Caption
ON dbo.TableA.Name LIKE '%' + dbo.TableB.Caption + '%'
OR dbo.TableB.Caption LIKE '%' + dbo.TableA.Name + '%'
That could explain why your query isn't working as expected.
As far as the most efficient way to do this, you'd want to have a standardized field in your table that you could use to JOIN on via equality (ex. a.col1 = b.col1), so that would entail stripping out the heart of each field that makes it join-worthy.
Update: If the important part is everything before the first period, then you want to use a combination of LEFT() and CHARINDEX() (and a CASE statement since not all strings contain a period):
SELECT NewField = CASE WHEN CHARINDEX('.',Name) > 0 THEN LEFT(Name,CHARINDEX('.',Name)-1)
ELSE Name
END
FROM YourTable
You could use the above in your JOIN too:
dbo.TableA.Name
INNER JOIN dbo.TableB.Caption
ON CASE WHEN CHARINDEX('.',TableA.Name) > 0 THEN LEFT(TableA.Name,CHARINDEX('.',TableA.Name)-1)
ELSE TableA.Name
END
= CASE WHEN CHARINDEX('.',TableB.Caption) > 0 THEN LEFT(TableB.Caption,CHARINDEX('.',TableB.Caption)-1)
ELSE TableB.Caption
END
How about this ( Not Tested)
dbo.TableA
INNER JOIN dbo.TableB
ON CHARINDEX(dbo.TableB.Caption, dbo.TableA.Name) > 0
Test it and don't forget Upvote OR accept.