Find an array values in another array - mysql

I have 2 strings that are not ordered for example orange is not always at second place in first line or other values.
apple, orange, water
water, juice, orange, something, apple
I want TRUE if all first line values exist in second line.
I've tried REGEXP 'apple|orange|water' but | is or not and that it gives me true if one of them exists there not all of them unless I write every possible sort.
I've also tried IN() but it needs 3 statements like :
... 'apple' IN('water', 'juice', 'orange', 'something', 'apple') AND
'orange' IN('water', 'juice', 'orange', 'something', 'apple') AND
'water' IN('water', 'juice', 'orange', 'something', 'apple') ...
Also tried LIKE but it should be like IN() in making queries.
I tried Match() Against() after all, but it doesn't work in join statement. look at this:
SELECT *
FROM t1
INNER JOIN t2
ON
t1.sth = t2.sth AND
MATCH(t1.sthelse) AGAINST(t2.sthelse IN BOOLEAN MODE)
There's 2 problems here. First, it doesn't work in join (also used where but second problem not solved. Second, AGAINST should be string :-? With Concat() I couldn't do the trick the error exists.
I want to do it not in these hard ways and also for my purpose, I should do it with mysql and cannot access php for manipulating these data.
+ I can change split character to anything.
Any idea... Appreciated.

My linux VM is still loading so the following code is tested in MS SQL. The pattern matching may break. For instance, your first string is "apple, orange, water" and your second string is "apple pie, orange pie, water bottle".
This is a good reference for converting string to table variable.
How to split string and insert values into table in SQL Server
DECLARE #FirstLineValues varchar(max), #SecondLineValues varchar(max)
DECLARE #eachValue VARCHAR(20)
SELECT #FirstLineValues = 'abc,3,3,5,6,3', #SecondLineValues = 'abc,2,3,4,5,6,7,8,9'
DECLARE #tblFirstLineValues TABLE(Value varchar(10))
DECLARE #tblSecondLineValues Table (value varchar(10))
-------------------------------------------------------------------------
DECLARE #ind int, #allExist bit
SET #ind = CHARINDEX(',',#FirstLineValues)
WHILE #ind > 0
BEGIN
SET #eachValue = SUBSTRING(#FirstLineValues, 1, #ind-1)
SET #FirstLineValues = SUBSTRING(#FirstLineValues, #ind+1, LEN(#FirstLineValues)-#ind)
INSERT INTO #tblFirstLineValues values (#eachValue)
SET #ind = CharIndex(',', #FirstLineValues)
END
SET #eachValue = #FirstLineValues
INSERT INTO #tblFirstLineValues values (#eachValue)
-------------------------------------------------------------------------
SET #ind = CHARINDEX(',',#SecondLineValues)
WHILE #ind > 0
BEGIN
SET #eachValue = SUBSTRING(#SecondLineValues,1,#ind-1)
SET #SecondLineValues = SUBSTRING(#SecondLineValues,#ind+1,LEN(#SecondLineValues)-#ind)
INSERT INTO #tblSecondLineValues values (#eachValue)
SET #ind = CharIndex(',',#SecondLineValues)
END
SET #eachValue = #SecondLineValues
INSERT INTO #tblSecondLineValues values (#eachValue)
-------------------------------------------------------------------------
SELECT #allExist = IIF(count(*) = 0, 1, 0)
FROM #tblFirstLineValues flv
LEFT OUTER JOIN #tblSecondLineValues slv ON flv.value = slv.value
WHERE slv.value IS NULL
-------------------------------------------------------------------------
select #allExist 'All first line values exist in second line'

Related

Take substring and use it in multiple where condition in sql

I have a string which has some values concatenated. Like 'Val1val2val3val4'.
I have a query like
Select * from table where var1 = Val1 and var2 = val2 and var3 = var3;
Val1 and val2 are length only 4 but val3 may differ in length. Val4 is of length 8 and no use.
I can form query with functions like var1 = substring (text, 1, 4), var2 = substring (text, 5, 8) and for var3 = substring (text, 9, Len(text) - 8).
But the problem is, i have to manually edit replace the value in 3 places in query each time in workbench. Which is a painful task in my case. Is it possible to just put the string in one place and make the SQL automatically take substrings and use in where clause conditions? I have only read access, cannot modify tables. Local variables like #var = Text, throws error code 1046. Hands tied for me. Need ideas if feasible.
You could put the input string into a derived table of one row, and cross-join that to your table:
SELECT ...
FROM (SELECT 'Val1val2val3val4' AS text) AS v
CROSS JOIN MyTable
WHERE var1 = substring(v.text, 1, 4) AND ...
Or you could use a user-defined variable and use it in a subsequent query:
SET #var = 'Val1val2val3val4';
SELECT ...
FROM MyTable
WHERE var1 = substring(#var, 1, 4) AND ...
You mentioned you got a 1046 error, but it's not clear how you were trying to assign it, so I can't guess what happened.
If you are sure that both #var1 and #var2 have length of 4 chars, then all you need is:
WHERE text LIKE CONCAT(#var1, #var2, #var3, REPEAT('_', 8))
If not then:
WHERE text LIKE CONCAT(#var1, #var2, #var3, REPEAT('_', 8))
AND CHAR_LENGTH(#var1) = 4
AND CHAR_LENGTH(#var2) = 4;
If the comparison should be case sensitive, change to:
WHERE text LIKE BINARY CONCAT(#var1, #var2, #var3, REPEAT('_', 8))

SET inside IF in MYSQL(?)

I'm new in MYSQL and I'm trying to do this:
UPDATE team
SET member1 = IF(member1=0, 001, SET member2 = IF(member2=0, 001, member2)) WHERE ID = ?;
This is not working, explain:
Each "member" has a different number (001, 002, 003...), I want to put the member "001" in the table "member1" but if this is ocupated (it has a value different of 0) set the member "001" in the table "member2" (a diferent table) but I think is not possible to put a SET inside of an IF. The id doesn't matters.
Thanks for attention ^^
No you can't join SET statements like this. It'll have to be worked around:
UPDATE `team`
SET
`member2` = CASE WHEN `member1` = 0 AND `member2` = 0 THEN '001' ELSE `member2` END,
`member1` = CASE WHEN `member1` = 0 THEN '001' ELSE `member1` END
WHERE
`id` = ?
/* optional filter: considering adding it if it does not bother the performance: */
AND (`member1` != 0 OR `member2` != 0)
;
Notes:
I used backticks around table and column names, I recommend you do so*
I used CASE/WHEN instead of IF, because IF is not ansi sql (it is specific to mysql)
You could also do two queries instead of one. That would allow you to use a filter in the where clause, so you don't have to update the column when it's not required.
*as pointed out by Bohemian, they are not ansi. I like to use them for the structural and visual help they provide.

How to optionally select multiple values for the same column in SQL?

So I am using Kentico CMS Desk 7 to generate reports for my company. In Kentico you create parameters and then create a table using sql and those parameters with the # symbol so whatever the user enters into that parameter, it will be the value of a parameter variable like #Status. I am wanting to add the ability for the user to either enter in one value, multiple values, or no values into the parameters, but I do not know how to implement the multiple values. I am a little new to SQL so bear with me. This is the SQL code I have right now:
select
ClaimNumber as 'Claim Number',
CustomerName as 'Customer Name',
DollarAmount as 'Dollar Amount',
[ReasonCode] as 'Reason code',
rt.[ReasonTypeName] as 'Reason type',
PlantNumber as 'Selling Company',
Status as 'Status'
from TABLE1 as c
join TABLE2 as u on u.UserID = c.DocumentCreatedByUserID
left join TABLE3 as rt on rt.ItemId = c.ReasonType
where ClaimDate between #FromDate and #ToDate
and ReasonCode like #ReasonCode
and ReasonType like #ReasonType
and (#SellingCompany = '' or PlantNumber = #SellingCompany)
and Status like #Status
order by ClaimNumber;
The parameter that I am trying to do this with is the selling company parameter denoted as #SellingCompany. Right now, this works for users not entering in any value and users entering in only one value, but I would like for users to have the ability to input multiple values separated by commas. I feel like an IN operator might work, but I am inexperienced in SQL and I don't know how I would implement this. I can't publish the data obviously because there is customer information, but this statement works as it is and I just need to know how to implement what I'm wanting to do. Thanks guys!
Have you tried this?
select
ClaimNumber as 'Claim Number',
CustomerName as 'Customer Name',
DollarAmount as 'Dollar Amount',
[ReasonCode] as 'Reason code',
rt.[ReasonTypeName] as 'Reason type',
PlantNumber as 'Selling Company',
Status as 'Status'
from TABLE1 as c
join TABLE2 as u on u.UserID = c.DocumentCreatedByUserID
left join TABLE3 as rt on rt.ItemId = c.ReasonType
where ClaimDate between #FromDate and #ToDate
and ReasonCode like #ReasonCode
and ReasonType like #ReasonType
and (#SellingCompany = '' or PlantNumber IN (#SellingCompany))
and Status like #Status
order by ClaimNumber;
I use this SQL function specifically when I need to cast a delimited string to a table value to use with the IN operator.
CREATE FUNCTION [dbo].[ParseIDListToTable]
(#vc_Ids nvarchar(MAX))
RETURNS #Id_table TABLE
(ID nvarchar(15))
BEGIN
DECLARE #in_Index1 AS INT, --Used to store ID delimiter(',') position in string
#vc_ID AS NVARCHAR(15)
/* initialize working variables */
SET #in_Index1 = CHARINDEX(',',#vc_Ids)
/* loop through ids in delimited string */
WHILE (#in_Index1 > 0 OR LEN(#vc_Ids) > 0)
BEGIN
/* parse out single id for processing */
IF #in_Index1 > 0
BEGIN
SET #vc_ID = Left(#vc_Ids,#in_Index1 - 1)
SET #vc_Ids = Right(#vc_Ids,Len(#vc_Ids) - #in_Index1)
END
ELSE
BEGIN
SET #vc_ID = #vc_Ids
SET #vc_Ids = ''
END
INSERT #Id_table (ID)
VALUES(#vc_ID)
/* prepare to loop */
SET #in_Index1 = CHARINDEX(',',#vc_Ids)
END
/* return the ids */
RETURN
END
Then I use it in my SELECT statement like so
WHERE PlantNumber IN (SELECT * FROM dbo.ParseIDListToTable('Microsoft,Apple,Dell'))
This should return the results you're looking for.

SQL Server 2008: Error converting data type nvarchar to float

Presently troubleshooting a problem where running this SQL query:
UPDATE tblBenchmarkData
SET OriginalValue = DataValue, OriginalUnitID = DataUnitID,
DataValue = CAST(DataValue AS float) * 1.335
WHERE
FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND ZEGCodeID IN
(SELECT ZEGCodeID FROM tblZEGCode
WHERE(ZEGCode = 'C004') OR
(LEFT(ZEGParentCode, 4) = 'C004'))
Results in the following error:
Msg 8114, Level 16, State 5, Line 1
Error converting data type nvarchar to float.
The really odd thing is, if I change the UPDATE to SELECT to inspect the values that are retrieved are numerical values:
SELECT DataValue
FROM tblBenchmarkData
WHERE FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND ZEGCodeID IN
(SELECT ZEGCodeID
FROM tblZEGCode WHERE(ZEGCode = 'C004') OR
(LEFT(ZEGParentCode, 4) = 'C004'))
Here are the results:
DataValue
2285260
1205310
Would like to use TRY_PARSE or something like that; however, we are running on SQL Server 2008 rather than SQL Server 2012. Does anyone have any suggestions? TIA.
It would be helpful to see the schema definition of tblBenchmarkData, but you could try using ISNUMERIC in your query. Something like:
SET DataValue = CASE WHEN ISNUMERIC(DataValue)=1 THEN CAST(DataValue AS float) * 1.335
ELSE 0 END
Order of execution not always matches one's expectations.
If you set a where clause, it generally does not mean the calculations in the select list will only be applied to the rows that match that where. SQL Server may easily decide to do a bulk calculation and then filter out unwanted rows.
That said, you can easily write try_parse yourself:
create function dbo.try_parse(#v nvarchar(30))
returns float
with schemabinding, returns null on null input
as
begin
if isnumeric(#v) = 1
return cast(#v as float);
return null;
end;
So starting with your update query that's giving an error (please forgive me for rewriting it for my own clarity):
UPDATE B
SET
OriginalValue = DataValue,
OriginalUnitID = DataUnitID,
DataValue = CAST(DataValue AS float) * 1.335
FROM
dbo.tblBenchmarkData B
INNER JOIN dbo.tblZEGCode Z
ON B.ZEGCodeID = Z.ZEGCodeID
WHERE
B.FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND (
Z.ZEGCode = 'C004' OR
Z.ZEGParentCode LIKE 'C004%'
)
I think you'll find that a SELECT statement with exactly the same expressions will give the same error:
SELECT
OriginalValue,
DataValue NewOriginalValue,
OriginalUnitID,
DataUnitID OriginalUnitID,
DataValue,
CAST(DataValue AS float) * 1.335 NewDataValue
FROM
dbo.tblBenchmarkData B
INNER JOIN dbo.tblZEGCode Z
ON B.ZEGCodeID = Z.ZEGCodeID
WHERE
B.FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND (
Z.ZEGCode = 'C004' OR
Z.ZEGParentCode LIKE 'C004%'
)
This should show you the rows that can't convert:
SELECT
B.*
FROM
dbo.tblBenchmarkData B
INNER JOIN dbo.tblZEGCode Z
ON B.ZEGCodeID = Z.ZEGCodeID
WHERE
B.FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND (
Z.ZEGCode = 'C004' OR
Z.ZEGParentCode LIKE 'C004%'
)
AND IsNumeric(DataValue) = 0
-- AND IsNumeric(DataValue + 'E0') = 0 -- try this if the prior doesn't work
The trick in the last commented line is to tack on things to the string to force only valid numbers to be numeric. For example, if you wanted only integers, IsNumeric(DataValue + '.0E0') = 0 would show you those that aren't.

Inserting images from file path -- Not getting value on the select statement

DECLARE #imgString varchar(800)
DECLARE #insertString varchar(3000)
DECLARE #imgNumber int
Declare #imgName varchar(100)
SET #imgNumber = 1
WHILE #imgNumber<> 101
BEGIN
SET #imgName = 'SELECT (items) FROM dbo.building_piclink'
SET #imgString = 'C:\Documents and Settings\Administrator\Desktop\photos\' + #imgName
SET #insertString = 'INSERT INTO dbo.building__ATTACH (DATA)
SELECT * FROM OPENROWSET(BULK N''' + #imgString + ''', SINGLE_BLOB) as tempImg'
SET #imgNumber = #imgNumber + 1
END
GO
I am having problems with the #imgName. I can't figure out how to get the value from the select statement not the (items) like below:
C:\Documents and Settings\Administrator\Desktop\photos\SELECT (items) FROM dbo.building_piclink
Thank you!
Your code has several problems:
1) You're selecting a file name from the view - but what if that view contains more than one entry?? Which filename are you selecting?? Your current code first of all doesn't work at all the way it is, and even if it were working - you're still potentially selecting hundreds of filenames into a single variable - which of course won't work....
So you'll need to fix this here first:
SET #imgName = 'SELECT (items) FROM dbo.building_piclink'
First of all - loose the single quotes:
SELECT #imgName = (items) FROM dbo.building_piclink
But now - do you have a unique ID that you can select for? Or do you want to get just the first entry (whatever that is) ??
So either you need:
SELECT #imgName = ImageFileName FROM dbo.building_piclink WHERE ..........
and fill in that WHERE clause with a condition that guarantees to return just a single row, or use TOP 1:
SELECT TOP (1) #imgName = ImageFileName FROM dbo.building_piclink
In that case - you'll just get exactly one filename - if you don't specify an ORDER BY, then there's no guarantee what you'll get - maybe you'll want to add a ORDER BY DueDate or something to prioritize which file names you get first.
2) Your code for loading the image data is non workable, either - what you need to do is build up the SQL statement as a string, and then execute it (called dynamic SQL) - something like this:
SET #imgString = 'C:\Documents and Settings\Administrator\Desktop\photos\' + #imgName
SET #insertString =
'INSERT INTO dbo.building__ATTACH (DATA)
SELECT * FROM OPENROWSET(BULK N''' + #imgString + ''', SINGLE_BLOB) as tempImg'
EXEC(#insertString) -- actually execute your SQL statement!
With these two fixes, you should be on the way to get this thing working