Who can write a more efficient query? - sql-server

I have this query, which works, but is there a more efficient way to write it?
SELECT *
FROM table (NOLOCK)
WHERE ((COL1 = 'aaa' AND COL2 = 'ee')
OR (COL1 = 'bbb' AND COL2 = 'ff')
OR (COL1 = 'ccc' AND COL2 = 'gg'))

First you will need a composite index with both COL1 and COL2 on the same index.
CREATE INDEX IX_TABLE_COL1_COL2
ON table (COL1, COL2);
Then I would use a union of simpler queries, that the engine won't have problems optimizing individually through the previous index. Expressions with OR seems to be harder for the engine to locate an optimal execution plan.
SELECT *
FROM table
WHERE COL1 = 'aaa' AND COL2 = 'ee'
UNION ALL
SELECT *
FROM table
WHERE COL1 = 'bbb' AND COL2 = 'ff'
UNION ALL
SELECT *
FROM table
WHERE COL1 = 'ccc' AND COL2 = 'gg'

Related

MSSQL Concatenate three columns and then use WHERE

I am using MSSQL server. What I am trying to do is concatenate 3 columns from the same table into one result so I can then use the WHERE clause on the results.
This is the command I would like to run:
select col1 + col2 + col3 as result from table where result like '%term%'
However I keep getting hit with Invalid column name 'result'
I have seen lots of answers about concatenating columns, but none seem to use the WHERE clause on them.
Thanks
Try This
SELECT col1 + col2 + col3 AS result
FROM TABLE
WHERE col1 LIKE '%term%'
OR col2 LIKE '%term%'
OR col3 LIKE '%term%'
OR
SELECT *
FROM (
SELECT col1 + col2 + col3 AS result
FROM TABLE
) t
WHERE result LIKE '%term%'
DECLARE #Search VARCHAR(10)='term'
SELECT Concat(col1, col2, col3) AS result
FROM table
WHERE Charindex(#Search, Concat(col1, col2, col3)) > 0
Use inner table to return result and search on returned column.
SELECT * FROM
(select col1 + col2 + col3 as result from [table] ) a
where result like '%term%'

T-SQL join with isnumeric

I have a database which looks like this: (well almost ;P)
TABLE1:
COL1 int (pk)
COL2 bit
COL3 int (FK to TABLE2 COL4)
TABLE2:
COL4 int (pk)
COL5 varchar(50)
Depending on the bit value the data contained in TABLE 2 will be numeric or not (1 is numeric).
If I run this query:
SELECT
CAST(COL5 AS INT)
FROM
TABLE1
INNER JOIN
TABLE2 ON COL4 = COL3 AND COL2 = 1 AND ISNUMERIC(COL5)
I get a conversion failure error:
Conversion failed when converting the varchar value '£0.00' to data type int
The query, without the cast, does not return this value, although the '£0.00' is in the table.
I was under the impression that the ON condition would be completed before the cast or am I wrong (obviously)?
Edit:
Running:
SELECT CASE WHEN COL5 LIKE '%[^0-9]%' THEN -1
WHEN CAST(COL5 as bigint) > 2147483647 THEN -1
ELSE cast(COL5 as int) END
FROM TABLE1
INNER JOIN TABLE2
ON COL4 = COL3 AND COL2 = 1
executes and returns no -1 values
Actually this is an issue with ISNUMERIC()
Things like: '$0.00', '£0.00', '1e10'
will all report as numeric, but you wont be able to convert them to INT or DECIMAL
Instead try this:
SELECT CAST(CAST(COL5 as money) as int)
FROM TABLE1
INNER JOIN TABLE2 ON COL4 = COL3 AND COL2 = 1 AND ISNUMERIC(COL5)
I have a blog article about the issues with ISNUMERIC():
http://www.thatcoderguy.co.uk/2014/04/07/the-problem-with-isnumeric/
The expressions in the SELECT part have nothing to do with those in the JOINs, so the fact that you cast them on the select will not affect in any way the join expression. You're correct, however, when saying that the ON thing completes before the SELECT list.
Since both col5 invocations are different and unrelated, you must repeat the cast:
SELECT cast(COL5 as int)
FROM TABLE1
INNER JOIN TABLE2 ON COL4 = COL3 AND
COL2 = 1 AND
ISNUMERIC(CAST(COL5 AS INT))

Identifying which value in where clause is incorrect?

My SQL kung-fu is not strong. I want to know if I can identify which value of a WHERE clause is incorrect.
So say I execute the following SQL statement....
SELECT col1, col2, col3 FROM dbo.myTable WHERE col1 = 'ABC' and col2 = 123
I want to be able to identify either that the value 'ABC' for col1 doesn't exist OR that the value 123 for col2 does not exist.
This would be within a single query, as I want to avoid two queries if possible.
Where I execute the first, and if rows exist then I execute the second if no rows then I can derive that col2 is wrong.
SELECT col1, col2, col3 FROM dbo.myTable WHERE col1 = 'ABC'
SELECT col1, col2, col3 FROM dbo.myTable WHERE col1 = 'ABC' and col2 = 123
I have considered
SELECT 1 as qRow, col1, col2, col3 FROM dbo.myTable WHERE col1 = 'ABC'
UNION
SELECT 2 as qRow, col1, col2, col3 FROM dbo.myTable WHERE col1 = 'ABC' and col2 = 123
and based on the qRow value i can determine which value is missing within the table, but wanted to now if there was any other solution
If you want to find where col1 is not ABC or col2 is not 123, you can do this:
SELECT col1 ,
col2 ,
col3
FROM dbo.myTable
WHERE col1 <> 'ABC'
OR col2 <> 123
Are you looking for something like
SELECT col1, col2, col3,
CASE
WHEN col1 = 'ABC' and col2 = 123 THEN 'both_true'
WHEN col1='ABC' THEN 'col1_true'
ELSE 'col2_true'
END AS value_check
FROM dbo.myTable WHERE col1 = 'ABC' or col2 = 123
I think probably you can use NOT EXISTS like
SELECT col1, col2, col3
FROM dbo.myTable
WHERE NOT EXISTS ( select 1 from dbo.myTable
where col1 = 'ABC' or col2 = 123)
SELECT col1, col2, col3, case when col1 <> 'ABC' then 'X' end as 'MissingCol1Abc',
case when col2 <> 123 then 'X' end as MissingCol2
FROM dbo.myTable
WHERE col1 = 'ABC' OR col2 = 123
Or did you mean you want to know when the column is null?
SELECT col1, col2, col3, case when is null col1 then 'X' end as 'MissingCol1Abc',
case when col2 is null then 'X' end as MissingCol2
FROM dbo.myTable
WHERE col1 = 'ABC' OR col2 = 123
If you use an OR instead of AND you could add a CASE statement to show the matching column:
SELECT col1, col2, col3,
CASE WHEN col1 = 'ABC' THEN 'True' ELSE 'False' END as Col1Match,
CASE WHEN col2 = '123' THEN 'True' ELSE 'False' END as Col2Match
FROM dbo.myTable
WHERE col1 = 'ABC' OR col2 = 123
Sample SQL Fiddle
You will see in the sample fiddle, that rows are only returned where one or both items match.

Trigger on insert from table 1 to insert row into table 2 if the data is unique, update if it's not

I need to make a trigger that, upon an insert into table1, checks if the same values from 3 columns in table2 match, if not it inserts that row into table2. If there is a match it then updates the row that matches. Here's what I've gathered so far, but it doesn't do the IF EXISTS check I need it to. I'm not certain how exactly to structure it in this case due to never having worked with triggers.
CREATE TRIGGER Trigger_Name on Table_Name
FOR INSERT
AS
BEGIN
INSERT INTO
TABLE 2
(
Col1,
Col2,
Col3,
Col4
)
SELECT
(
Col1,
Col2,
Col3,
Col4
)
FROM
INSERTED
GO
The IF EXISTS criteria need to see if table1.col1=table2.col1, table1.col2=table2.col2, table1.col3,table2.col3
Using SQL server 2008. Any help is much appreciated
UPDATE table2
SET col1 = inserted.col1
, col2 = inserted.col2
, col3 = inserted.col3
, col4 = inserted.col4
FROM table2
INNER
JOIN inserted
ON inserted.col1 = table2.col1
AND inserted.col2 = table2.col2
AND inserted.col3 = table2.col3
;
INSERT INTO table2 (col1, col2, col3, col4)
SELECT col1
, col2
, col3
, col4
FROM inserted
WHERE NOT EXISTS (
SELECT *
FROM table1
WHERE col1 = inserted.col1
AND col2 = inserted.col2
AND col3 = inserted.col3
)
;

Removing duplicate combinations from result set in SQL Server

I have a table with two columns with data like this:
1,2
1,3
1,4
2,1
2,2
3,1
I want to select just unique combinations, so out of those I would end up with:
1,2
1,3
1,4
2,2
because 1,2 is the same combination as 2,1 etc
How would I go about that in a SQL statement?
In reality, my table has a third column and I want to add a where clause based on that third column so that only those rows are considered
SELECT * FROM (
SELECT
CASE WHEN Col1 <= Col2 THEN Col1 ELSE Col2 END AS Col1,
CASE WHEN Col1 <= Col2 THEN Col2 ELSE Col1 END AS Col2
FROM
MyTable
) Ordered
GROUP BY
Col1, Col2
You could do it without the subquery by GROUPing on the CASE expressions, but it's longer to read.
Another way to achieve the same thing:
SELECT a, b
FROM tableX
WHERE a <= b
AND (other conditions)
UNION
SELECT b, a
FROM tableX
WHERE a > b
AND (other conditions) ;
This variation may be different (regarding efficiency), depending on the indexes you have:
SELECT *
FROM
( SELECT a, b
FROM tableX
WHERE (other conditions)
UNION
SELECT b, a
FROM tableX
WHERE (other conditions)
) AS tmp
WHERE a <= b ;
You can try something like:
select distinct col1, col2 from table
where col2 + '-' + col1 not in (select col1 + '-' + col2 from your_table)
Notice that you have to concatenate the fields and it depends of the column type (col1 + '-' + col2 works well with char and varchar types)
How about:
SELECT
COL1, COL2, COUNT(*)
FROM
Your_Table
GROUP BY
COL1, COL2

Resources