I have a column where I have 0 or 1. I like to do the following set up:
If 0 than put / use the Region_table (here I have regions like EMEA, AP,LA with finished goods only) and when it 1 then put / use the Plant_table (here I have plants with non-finished goods) data's.
I tried to write it in 2 different statements but it is not good:
,Case
when [FG_NFG_Selektion] = '0' Then 'AC_region'
End as 'AC_region'
,Case
when [FG_NFG_Selektion] = '1' Then 'AC_plant'
End as 'AC_plant'
I'm not 100% clear on what you're looking for, but if you want to get data from different tables based on the value in the [FG_NFG_Selektion] field, you can do something like this:
SELECT
CASE
WHEN [FG_NFG_Selektion] = '0' THEN r.some_col -- If 0, use value from "region" table
WHEN [FG_NFG_Selektion] = '1' THEN p.some_col -- If 1, use value from "plant" table
END AS new_field
FROM MyTable t
LEFT JOIN AC_region r ON t.pk_col = r.pk_col -- get data from "AC_region" table
LEFT JOIN AC_plant p ON t.pk_col = p.pk_col -- get data from "AC_plant" table
;
If [FG_NFG_Selektion] is a numeric field, then you should remove the single quotes: [FG_NFG_Selektion] = 0.
I would strongly recommend putting the conditions in the ON clauses:
SELECT COALESCE(r.some_col, p.some_col) as som_col
FROM t LEFT JOIN
AC_region r
ON t.pk_col = r.pk_col AND
t.FG_NFG_Selektion = '0' LEFT JOIN
AC_plant p
ON t.pk_col = p.pk_col AND
t.FG_NFG_Selektion = '1';
Why do I recommend this? First, this works correctly if there are multiple matches in either table. That is probably not an issue in this case, but it could be in others. You don't want to figure out where extra rows come from.
Second, putting the conditions in the ON clause allows the optimizer/execution engine to take advantage of them. For instance, it is more likely to use FG_NFG_Selektion in an index.
Related
I am attempting to Join tables based on a CONCAT expression containing different text criteria.
I have tried a inefficient method that just takes way too long to query.
SELECT
sf.displayId,
-- tw.displayText,
CASE
WHEN tw.DisplayText IN ('N/A', 'NotApplicable', 'Not Applicable')
THEN 'Not Applicable'
ELSE REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(tw.DisplayText,'client','Client'),'approved','Approved'),'rejected','Rejected'),'review','Review'),'Requirement','Requirement'),'open','Open'),'submitted','Submitted'),'complete','Complete'),'incomplete','Incomplete'),'pending','Pending'),'resubmit','Resubmit'),'Awaiting review','Awaiting Review')
END AS AuditStatus
FROM Connect.Data.supplier_form sf
JOIN Connect.Data.translation tw
ON ((CONCAT('workflowStepName' , sf.workflowStatusId) = tw.translationField) OR (CONCAT('workflowStepMessage' , sf.workflowStatusId) = tw.translationField))
AND tw.language = 'en'
WHERE sf.deleted = 0
AND tw.displayText IN ('Awaiting Review','Awaiting review')
ORDER BY sf.displayId
OFFSET 0 ROWS
FETCH NEXT 100 ROWS ONLY;
I want to JOIN Connect.Data.supplier_form sf based on the CONCAT expression in a far more efficient way.
I'm not sure how good the SQL optimizer is in SQL Server, so you may try to flip the order of the join condition to make it easier to use an index. I would do two things:
I would change the JOIN condition to:
JOIN Connect.Data.translation tw
ON tw.language = 'en'
AND tw.translationField in (
CONCAT('workflowStepName' , sf.workflowStatusId),
CONCAT('workflowStepMessage' , sf.workflowStatusId)
)
And I would add the index:
create index ix1 on Connect.Data.translation(language, translationField);
Give it a try and let us know if it improves the performance.
I'm utilizing four separate tables and i can't seem to figure out why my DISTINCT isn't filtering the results. I'm trying to get a single result for each acct.Name in this query. Regardless if i use DISTINCT or not, i get the exact same results.
Select DISTINCT
acct.Name,
inv.InvoiceNumber,
acct.AccountNumber,
addr.Line1,
addr.Line2,
addr.Line3,
addr.City,
addr.StateOrProvince,
addr.postalcode
FROM InvoiceBase inv, AccountBase acct
JOIN AccountExtensionBase base
ON base.AccountId = acct.AccountId
JOIN CustomerAddressBase addr
ON addr.ParentId = acct.AccountId
WHERE
inv.AccountId=acct.AccountId And
base.New_cocat_master = 1 And
base.New_CompanyId = 1 And
inv.StateCode = 0 And
inv.Name = '2013 ' + acct.AccountNumber
ORDER by acct.Name
The first result i get now has the first three values (acct.Name, inv.InvoiceNumnber, acct.AccountNumber) and the rest of the columns are blank. The second row has all of the columns with the information. I'm just trying to make the acct.Name to be DISTINCT
The rows are DISTINCT
This may be confusing when you are selecting multiple strings, since there might be hidden characters/spaces. Select the length of each one of those fields and compare the so called duplicate rows.
Turns out all i had to do was add in a simple clause in the WHERE, since the address is required for a valid invoice (where to send it):
WHERE
base.New_cocat_master = 1 And
base.New_CompanyId = 1 And
inv.StateCode = 0 And
inv.Name = '2013 ' + acct.AccountNumber And
addr.Line1 IS NOT NULL
I have the following tables. I want to run a query but I think my beginner tsql level won't help here.. It probably also is a situation where I have a bad database design.
Basically I need to select all fields from tblPhotoGalleries. Also I need to create a seperate field named GalleryCategoryName.
GalleryCategoryName field will be the pCatName in tblPhotoGalleryCats.
If pCatName in tblPhotoGalleryCats = '0', then that would mean, ConnectedNewsCatID is something other than 0. In that case;
GalleryCategoryName will be the CategoryName field from tblNewsCategories where CategoryID = ConnectedNewsCatID
Use a left join on the news category table, and use a case expression to choose between the names:
select
g.pgID, g.gName,
GalleryCategoryName = case c.pCatName when '0' then n.CategoryName else c.pCatName end
from tblPhotoGalleries g
inner join tblPhotoGFalleryCats c on c.pCatID = g.FK_pCatID
left join tblNewsCategories n on n.CategoryOd = c.ConnectedNewsCatID
Try starting here:
select *,
case when PGC.pCatName = '0' then NC.CategoryName else PGC.pCatName end as [CatName]
from tblPhotoGalleries as PG inner join
tblPhotoGalleryCats as PGC on PGC.pCatID = FK_pCatID left outer join
tblNewsCategories as NC on NC.CategoryId = ConnectedNewsCatID
I have written a query in access and now I am trying to write the same in SQL Server I am getting following error:
Msg 164, Level 15, State 1, Procedure OQRY_STEP_1_1, Line 15
Each GROUP BY expression must contain at least one column that is not an outer reference.
My SQL Query is as follows:
SELECT
ns11.SYS_ID,
ns11.SUB_NET_ID,
ns11.TEMP_ID,
ns11.EQ_ID,
ns11.NODE_NAME,
ns11.EQ_NAME,
ns11.VAR_NAME,
ns11.VAR_SET,
ns11.VAR_SUBSET,
ns11.EQ_TYPE,
ns11.RHS_RELN,
ns11.RHS_OBJECT,
ns11.EQ_TP_OFFSET,
ns11.RHS_TP_OFFSET,
ns11.RETAIN,
nmte.RHS_VAR_SET,
nmte.RHS_VAR_SUBSET,
nmte.RHS_VAR_NAME,
0 AS RHS_VAR_TYPE,
CASE
WHEN [asp].[VALUE] = NULL THEN 0
ELSE [asp].[VALUE]
END RHS_VALUE
INTO ##OT_STEP_1_1
FROM (##NT_STEP_1_1 ns11
INNER JOIN ##NT_MASTER_TEMP_EQUATION nmte
ON (ns11.SYS_ID = nmte.SYS_ID)
(ns11.SUB_NET_ID = nmte.SUB_NET_ID)
AND (ns11.TEMP_ID = nmte.TEMP_ID)
AND (ns11.EQ_ID = nmte.EQ_ID)
AND (ns11.NODE_NAME = nmte.NODE_NAME)
AND (nmte.SYS_ID = ns11.SYS_ID)
AND (nmte.SUB_NET_ID = ns11.SUB_NET_ID))
LEFT JOIN AMST_SIM_PAR asp ON
(nmte.SYS_ID = asp.SYS_ID)
AND (nmte.SUB_NET_ID = ns11.SUB_NET_ID)
AND (nmte.RHS_VAR_NAME = asp.VAR_NAME)
GROUP BY
ns11.SYS_ID,
ns11.SUB_NET_ID,
ns11.TEMP_ID,
ns11.EQ_ID,
ns11.NODE_NAME,
ns11.EQ_NAME,
ns11.VAR_NAME,
ns11.VAR_SET,
ns11.VAR_SUBSET,
ns11.EQ_TYPE,
ns11.RHS_RELN,
ns11.RHS_OBJECT,
ns11.EQ_TP_OFFSET,
ns11.RHS_TP_OFFSET,
ns11.RETAIN,
nmte.RHS_VAR_SET,
nmte.RHS_VAR_SUBSET,
nmte.RHS_VAR_NAME,
0,
CASE
WHEN [asp].[VALUE] = NULL THEN 0
ELSE [asp].[VALUE]
END
ORDER BY
CASE
WHEN [asp].[VALUE] = NULL THEN 0
ELSE [asp].[VALUE]
END;
I am not sure why it is not taking 0 in the group by clause?
I think the GROUP BY ..., 0, ... is the issue here. Try removing that 0 from there. There is no point grouping by a constant.
Sidenote:
CASE WHEN [AMST_SIM_PAR].[VALUE] = NULL
THEN 0
ELSE [AMST_SIM_PAR].[VALUE]
END
should be be written with IS NULL instead of = NULL or as:
COALESCE( [AMST_SIM_PAR].[VALUE], 0 )
I think the constant '0' in your group by is the problem.
Are you using ANSI_NULLS? SQL-92 defines "= NULL" or "<> NULL" to always return false. Try changing "= NULL" to "IS NULL".
Also in your left join you have a criteria that doesn't match the outer table. The inner join already links SUB_NET_ID on those two tables so you can remove it from your left join.
Since you are not taking any aggregates, why not just use DISTINCT instead of repeating all that noise in the GROUP BY? Also the ORDER BY is not very useful because you are using SELECT INTO, which creates a new table, which by definition is an unordered set of rows. In order to get the data out of that table in the right "order" you should use an ORDER BY when you eventually select out of it. If you want the data optimized for joins or what have you after the table is created, create a clustered index after the SELECT INTO. Finally, why are you using ##global temp tables? You know that two users can't execute this code at the same time, right?
All that said, here is a much simpler and easier to read version:
SELECT DISTINCT
n.SYS_ID,
n.SUB_NET_ID,
n.TEMP_ID,
n.EQ_ID,
n.NODE_NAME,
n.EQ_NAME,
n.VAR_NAME,
n.VAR_SET,
n.VAR_SUBSET,
n.EQ_TYPE,
n.RHS_RELN,
n.RHS_OBJECT,
n.EQ_TP_OFFSET,
n.RHS_TP_OFFSET,
n.RETAIN,
te.RHS_VAR_SET,
te.RHS_VAR_SUBSET,
te.RHS_VAR_NAME,
RHS_VAR_TYPE = 0,
RHS_VALUE = COALESCE(a.VALUE, 0)
INTO ##OT_STEP_1_1
FROM ##NT_STEP_1_1 AS n
INNER JOIN ##NT_MASTER_TEMP_EQUATION AS te
ON n.SYS_ID = te.SYS_ID
AND n.SUB_NET_ID = te.SUB_NET_ID
AND n.TEMP_ID = te.TEMP_ID
AND n.EQ_ID = te.EQ_ID
AND n.NODE_NAME = te.NODE_NAME
AND te.SYS_ID = n.SYS_ID
AND te.SUB_NET_ID = n.SUB_NET_ID
LEFT OUTER JOIN dbo.AMST_SIM_PAR AS a
ON te.SYS_ID = a.SYS_ID
AND te.SUB_NET_ID = n.SUB_NET_ID
AND te.RHS_VAR_NAME = a.VAR_NAME;
Keep in mind I am using SQL 2000
I have two tables.
tblAutoPolicyList contains a field called PolicyIDList.
tblLossClaims contains two fields called LossPolicyID & PolicyReview.
I am writing a stored proc that will get the distinct PolicyID from PolicyIDList field, and loop through LossPolicyID field (if match is found, set PolicyReview to 'Y').
Sample table layout:
PolicyIDList LossPolicyID
9651XVB19 5021WWA85, 4421WWA20, 3314WWA31, 1121WAW11, 2221WLL99 Y
5021WWA85 3326WAC35, 1221AXA10, 9863AAA44, 5541RTY33, 9651XVB19 Y
0151ZVB19 4004WMN63, 1001WGA42, 8587ABA56, 8541RWW12, 9329KKB08 N
How would I go about writing the stored proc (looking for logic more than syntax)?
Keep in mind I am using SQL 2000.
Select LossPolicyID, * from tableName where charindex('PolicyID',LossPolicyID,1)>0
Basically, the idea is this:
'Unroll' tblLossClaims and return two columns: a tblLossClaims key (you didn't mention any, so I guess it's going to be LossPolicyID) and Item = a single item from LossPolicyID.
Find matches of unrolled.Item in tblAutoPolicyList.PolicyIDList.
Find matches of distinct matched.LossPolicyID in tblLossClaims.LossPolicyID.
Update tblLossClaims.PolicyReview accordingly.
The main UPDATE can look like this:
UPDATE claims
SET PolicyReview = 'Y'
FROM tblLossClaims claims
JOIN (
SELECT DISTINCT unrolled.LossPolicyID
FROM (
SELECT LossPolicyID, Item = itemof(LossPolicyID)
FROM unrolling_join
) unrolled
JOIN tblAutoPolicyList
ON unrolled.ID = tblAutoPolicyList.PolicyIDList
) matched
ON matched.LossPolicyID = claims.LossPolicyID
You can take advantage of the fixed item width and the fixed list format and thus easily split LossPolicyID without a UDF. I can see this done with the help of a number table and SUBSTRING(). unrolling_join in the above query is actually tblLossClaims joined with the number table.
Here's the definition of unrolled 'zoomed in':
...
(
SELECT LossPolicyID,
Item = SUBSTRING(LossPolicyID,
(v.number - 1) * #ItemLength + 1,
#ItemLength)
FROM tblLossClaims c
JOIN master..spt_values v ON v.type = 'P'
AND v.number BETWEEN 1 AND (LEN(c.LossPolicyID) + 2) / (#ItemLength + 2)
) unrolled
...
master..spt_values is a system table that is used here as the number table. Filter v.type = 'P' gives us a rowset with number values from 0 to 2047, which is narrowed down to the list of numbers from 1 to the number of items in LossPolicyID. Eventually v.number serves as an array index and is used to cut out single items.
#ItemLength is of course simply LEN(tblAutoPolicyList.PolicyIDList). I would probably also declared #ItemLength2 = #ItemLength + 2 so it wasn't calculated every time when applying the filter.
Basically, that's it, if I haven't missed anything.
If the PolicyIDList field is a delimited list, you have to first separate the individual policy IDs and create a temporary table with all of the results. Next up, use an update query on the tblLossClaims with 'where exists (select * from #temptable tt where tt.PolicyID = LossPolicyID).
Depending on the size of the table/data, you might wish to add an index to your temporary table.