Query very slow with bit fields and full text search - sql-server

I have a strange problem, if I execute the following query, Sql Server (2008 and 2016) needs about 35 seconds to complete.
SELECT DISTINCT F.FilterTitle, F.FilterSlug, F.FilterOrderList, F.FilterType
FROM products p
JOIN products_translations pt ON pt.ProductId = p.Id AND pt.Culture = 'it'
JOIN facets F ON F.ProductId = p.Id AND F.Culture = 'it' AND F.FilterType = 2
JOIN products_categories pc ON pc.productId = p.id
JOIN categories C ON pc.CategoryId = C.Id
JOIN categories_slugs cps ON cps.CategoryId = C.ParentCategoryId AND cps.Culture = 'it'
JOIN categories_slugs cs ON cs.CategoryId = C.Id AND cs.Culture = 'it'
WHERE cps.value = 'string1' AND cs.value = 'string2'
AND CONTAINS(pt.DescriptionForSearch, '"value*"', LANGUAGE 1040) --this is a full text
AND p.Visible = 1 AND p.Payments = 0 --both are bit fields
ORDER BY F.FilterType, F.FilterOrderList, F.FilterTitle;
If I comment the line
and p.Visible = 1 and p.Payments = 0
the query needs just a couple of ms. The same if I remove the line
and contains(pt.DescriptionForSearch, '"value*"' , language 1040)
and leave the other statement intact. I also created two indexes for both the bit fields without changes.
Can someone shed some light on why this is happening?
UPDATE
At this link the two execution plans that I forgot to include.

Related

SQL Server MERGE with conditions not merging

I'm trying to do a simple update of my table when the collector has different data than the final table. I'm using the code below. When the first SELECT runs it tells me that the two columns both have data in them. After the MERGE statement runs, and I do the new SELECT, both of the columns are still showing as NULL. The merge isn't updating anything.
Have I messed up the MERGE syntax somehow?
The production code I have also includes WHEN NOT MATCHED and other items. This is just a small example to demonstrate the problem.
SELECT l.Region_Name, l.Region_Code
FROM dbo.Collector_Locations l
WHERE l.id = 1038
MERGE INTO dbo.Locations AS T
USING dbo.Collector_Locations S ON T.id = S.id
WHEN MATCHED AND (T.Region_Name <> S.Region_Name OR T.Region_Code <> S.Region_Code)
THEN
UPDATE SET T.Region_Name = S.Region_Name,
T.Region_Code = S.Region_Code;
SELECT l.Region_Name, l.Region_Code
FROM dbo.Locations l
WHERE l.id = 1038
Changing the query to accomodate NULL values:
MERGE dbo.Locations AS T
USING dbo.Collector_Locations S
ON T.id = S.id
WHEN MATCHED AND (ISNULL(T.Region_Name,'a') <> S.Region_Name OR ISNULL(T.Region_Code,'a') <> S.Region_Code) THEN UPDATE SET
T.Region_Name = S.Region_Name,
T.Region_Code = S.Region_Code;
Apart from that, the syntax looks fine. This should do the trick.
EDIT:
I would however go for a UPDATE statement in this scenario:
UPDATE dbo.Locations
SET T.Region_Name = S.Region_Name,T.Region_Code = S.Region_Code
FROM dbo.Locations T
INNER JOIN dbo.Collector_Locations S
ON T.id = S.id AND (T.Region_Name <> S.Region_Name OR T.Region_Code <> S.Region_Code)
You could also take our the last set of join condition, since the expected end result is going to be the same:
UPDATE dbo.Locations
SET T.Region_Name = S.Region_Name,T.Region_Code = S.Region_Code
FROM dbo.Locations T
INNER JOIN dbo.Collector_Locations S
ON T.id = S.id

IS NULL being ignored

I am trying to run a query in T-SQL to pull back a data set based on a column being null.
This is a simplified version of the code:
SELECT
T1.Col1, T1.Col2,
T1.Col3, T1.Col4
FROM
table1 AS T1
INNER JOIN
table2 AS T2 ON T1.Col2 = T2.Col3
WHERE
T2.Col4 IS NULL
Problem is, the result includes rows where T2.Col4 are NULL and also not NULL, it's like the WHERE clause doesn't exist.
Any ideas would be greatly
UPDATE - full version of code:
SELECT
M.ref
,C.cname
,CL.clname
,C.ccity
,M.productLine
,M.code
,CL.date
,M.dept
,DPT.group
,TK2.tkname
,TK2.tkdept
FROM DB.dbo.manage AS M
OUTER JOIN DB.dbo.ClientManageRelationship AS CMR
ON CMR.RelatedEntityID = M.EntityID
OUTER JOIN DB.dbo.Client AS C
ON C.EntityID = CMR.EntityID
INNER JOIN DB.dbo.ManageCustomerRelationship AS MCR
ON MCR.EntityID = M.EntityID
INNER JOIN DB.dbo.Customer AS CL
ON CL.EntityID = MCR.RelatedID
INNER JOIN DB.dbo.timek AS TK
ON TK.tki = M.tkid
LEFT JOIN (SELECT Group = division, [Department] = newdesc, deptcode FROM DB.csrt.vw_rep_p_l_dept) AS DPT
ON tkdept = DPT.dept
LEFT JOIN (SELECT Name = TK2.tkfirst + ' ' + TK2.tklast, TK2.tki, TK2.dept, TK2.loc FROM DB.dbo.timek as TK2 WITH(NOLOCK)) AS TK2
ON TK2.tki = M.tkid
WHERE DPT.Department = 'Casualty'
AND UPPER (C.ClientName) LIKE '%LIMITED%'
AND CL.date > '31/12/2014'
AND CL.Date IS NULL
AND TK.tkloc = 'loc1' OR TK.tkloc = 'loc2'
ORDER BY M.ref
My first answer would be because you're using INNER JOIN. This only returns matches between the 2 tables. TRY FULL OUTER JOIN which will return all values regardless of matches and will include NULLS.
If you were looking to return all rows regardless of matches including NULLS from only one of the tables then use RIGHT or LEFT JOIN.
Say i had 2 tables ('Person' and 'Figure'). Not every person may have entered a figure on any one day. But an example may be i want to return all people regardless of whether they entered a figure or not on a certain day.
My initial approach to this would be a LEFT join because i want to return of all the people(left table) regardless of there being any matches in the figure table(right table)
FROM Person P
LEFT JOIN Figure F
ON P.ID = F.ID
This would produce a result such as
Name Figure
Sam 20
Ben 30
Matt NULL
Simon NULL
Whereas,
An inner join would produce only matching values not including nulls
Name Figure
Sam 20
Ben 30
Left join works the same way as right join but in the opposite direction. This is most likely the problem you were facing. But i hope this helped
I think the problem is in the last part of the where condition.
You should use brackets.
`WHERE DPT.Department = 'Casualty'
AND UPPER (C.ClientName) LIKE '%LIMITED%'
AND CL.date > '31/12/2014'
AND CL.Date IS NULL
AND (TK.tkloc = 'loc1' OR TK.tkloc = 'loc2')`
or
`WHERE DPT.Department = 'Casualty'
AND UPPER (C.ClientName) LIKE '%LIMITED%'
AND CL.date > '31/12/2014'
AND CL.Date IS NULL
AND TK.tkloc IN ('loc1', 'loc2')`

SQL server 2012 - Query on retrieving matching records from a table by cross checking with two other tables

I have three tables (say A,B and C) with same column names and datatype. And these tables can be joined using four unique columns, say name,company,Seq_Number and role. Now I want to select records of particular role from table A and cross check them with the records in Table B and C.If they do not exist in both the tables, then we need to deactivate/remove those records from Table A. The problem is, the records which does not exist in table B might exist in Table C. So, I need to remove the records of particular role only if they don't exist in both B & C tables. I tried with the below query. But it is not returning the expected result. Kindly help me on this
SELECT DISTINCT FAT_Cust.name
, FAT_Cust.Company
, FAT_Cust.role
, FAT_Cust.Seq_Number
, Cust.name
, Cus.Company
, Cust.role
, Cust.Seq_Numberfrom (
SELECT DISTINCT ALC.NAME, ALC.Company, ALC.ROLE, ALC.Seq_Number
FROM AL_Customer ALC
INNER JOIN BL_Customer LPC ON ALC.NAME = LPC.NAME
AND ALC.Company = LPC.Company
AND ALC.ROLE = LPC.ROLE
AND ALC.Seq_Number = LPC.Seq_Number
AND ALC.Record_Active = 1
UNION SELECT DISTINCT ALC.NAME, ALC.Company, ALC.ROLE, ALC.Seq_Number
FROM AL_Customer ALC
INNER JOIN CL_Customer CLC ON ALC.NAME = CLC.NAME
AND ALC.Company = CLC.Company
AND ALC.ROLE = CLC.ROLE AND ALC.Seq_Number = CLC.Seq_Number
AND ALC.Record_Active = 1
) Cust
RIGHT OUTER JOIN AL_Customer FAT_Cust ON FAT_Cust.NAME = Cust.NAME
AND FAT_Cust.Company = Cust.Company
AND FAT_Cust.ROLE = Cust.ROLE
AND FAT_Cust.Seq_Number = Cust.Seq_Number
AND FAT_Cust.Record_Active = 1
WHERE Cust.NAME IS NULL
AND Cust.Company IS NULL
AND Cust.ROLE IS NULL
AND Cust.Seq_Number IS NULL
AND Cust.ROLE < > 'OWN'
Please try the query given below
SELECT ALC.* FROM AL_Customer ALC
LEFT JOIN BL_Customer BPC ON ALC.NAME = BPC.NAME
AND ALC.Company = BPC.Company
AND ALC.ROLE = BPC.ROLE
AND ALC.Seq_Number = BPC.Seq_Number
AND ALC.Record_Active = 1
AND BLC.Record_Active = 1
LEFT JOIN CL_Customer CPC ON ALC.NAME = CPC.NAME
AND ALC.Company = CPC.Company
AND ALC.ROLE = CPC.ROLE
AND ALC.Seq_Number = CPC.Seq_Number
AND ALC.Record_Active = 1
AND CLC.Record_Active = 1
WHERE ALC.Record_Active = 1
AND (BPC.NAME IS NULL)
AND (CPC.NAME IS NULL)
you can add more condition is where class to narrow down the matching criteria. the above query is assuming that name is present for all the records in the table. I hope this will resolve your issue.

sql query assistance

I have a sql that is as under:
SELECT ib.branch_no,
ib.on_hand,
p.weightedav,
p.item_code,
FROM physical p
INNER JOIN
item_branch as ib on p.item_code = ib.item_code
WHERE ib.on_hand <> 0
This SQL returns only those branch_no that have on_hand <> 0.
I am trying to get all the branch_nos irrespective of the on_hand field, but while still using the where on_hand clause.
Taking the on_hand clause away solves my problem, but gives me large amount of un-needed rows with 0's.
I am using SQL SERVER 2008 R2.
Thanks in advance for any guidance. Please apologize if I am missing any information.
------------------------------------------ENTIRE SQL QUERY (Updated)---------------------------------------------
select
ib.branch_no,
p.weighted_av,
p.item_code,
p.x_value,
p.y_value,
ib.on_hand,
p.on_hand as PhysicalOH,
ip.price,
i.item_code as StyleCode,
i.description,
i.cat1,
i.cat2,
i.cat3,
i.cat4,
np.is_style_yn,
si.supplier_code ,
ysv.sort as YSort
from physical as p
left outer JOIN
item_branch as ib on p.item_code = ib.item_code -- and ib.on_hand <> 0
INNER JOIN
item_price as ip on p.item_code = ip.item_code and ip.price_type = 'P1'
INNER JOIN
style_values as sv on p.style_code = sv.style_code and p.x_value = sv.value
INNER JOIN
style_values as ysv on p.style_code = ysv.style_code and p.y_value = ysv.value and ysv.axis = 'Y'
INNER JOIN
ITEM as i on p.style_code = i.item_code
INNER JOIN
NON_PHYSICAL as np ON i.item_code = np.item_code and np.is_style_yn = 1
INNER JOIN
supplier_item as si ON i.item_code = si.item_code and si.pref_supp_no = 1
where --ib.on_hand <> 0 and
sv.axis = 'X' and
i.item_code in
(SELECT ITEM.item_code
FROM ITEM
INNER JOIN
NON_PHYSICAL ON ITEM.item_code = NON_PHYSICAL.item_code
LEFT JOIN
supplier_item ON Item.item_code = supplier_item.item_code and pref_supp_no = 1
WHERE NON_PHYSICAL.is_style_yn = 1 and ITEM.cat1 = 'Verge Sportswear Ltd' )
order by
si.supplier_code,
i.cat4,
i.cat3,
i.cat2,
i.cat1,
sv.sort
Try this:
SELECT ib.branch_no,
ib.on_hand,
p.weightedav,
p.item_code,
FROM physical p
INNER JOIN
item_branch as ib on (p.item_code = ib.item_code AND ib.on_hand <> 0)

SQLITE Complex select statement. Help me speed it up

Some may or may not consider this a complex statement, but for me (since I've only been doing statement for about a month) this one is. The below statement returns me the exact results I am looking for, but my problem is that it take over 95 seconds to run on a iMac. I need this statement to run on an iPhone. Can anyone thing of a better (quicker) way to do this?
select categories.category
from categories join categories_listings
where categories_listings.category_id = categories.id
and categories.association_id = 1
and (select count(*)
from (select (
select categories.category
from categories left join categories_listings
where categories_listings.category_id = categories.id
and categories.association_id = 1
and listings.id = categories_listings.listing_id) as region
from listings left join chamber_specifics
on chamber_specifics.listing_id=listings.id
where region = categories.category
and listings.association_id=1
and listings.status = 1
and downtown='Y')) >0
group by categories.category;
Let me know if more info is needed.
Thanks!
I came up with a statement that gets me the same results as in my question, but much fast at about 0.062 seconds to complete. Below is my Statement: (Thanks Rudu for the direction!)
select (
select categories.category
from categories left join categories_listings
where categories_listings.category_id = categories.id
and categories.association_id = 1
and listings.id = categories_listings.listing_id) as region
from listings left join chamber_specifics
on chamber_specifics.listing_id=listings.id
where listings.association_id=1
and listings.status = 1
and downtown='Y'
group by region

Resources