Excluding certain results of the query SQL Server - sql-server

I have 3 tables: CLIENT, FEATURE, CLIENT_FEATURE
Table CLIENT: id_client, name, surname, address
Table FEATURE: id_feature, feature_txt
Table FEATURE_CLIENT: id_fc, fc_id_client, fc_id_feature
One client can have multiple features.
If I want to see clients with desired 1 feature:
SELECT
[id_client], [name], [surname], [address], [id_feature],
[feature_txt], [id_fc], [fc_id_client], [fc_id_feature]
FROM
[client]
LEFT JOIN
[feature] ON fc_id_client = id_client
WHERE
fc_id_feature = 1
It is ok, but If the client has the feature 1 and 20 and I want to search for clients without feature 20
I tested:
SELECT
[id_client], [name], [surname], [address],[id_feature],
[feature_txt], [id_fc], [fc_id_client], [fc_id_feature]
FROM
[client]
LEFT JOIN
[feature] ON fc_id_client = id_client AND fc_id_client <> 20
WHERE
fc_id_client = 1
but it is not working.

SELECT *
FROM
[client]
INNER JOIN
[feature_client] ON
client.id_client = feature_client.fc_id_client
INNER JOIN
[feature] ON
feature_client.fc_id_feature = feature.id_feature
WHERE
fc_id_feature = 1 AND
id_client NOT IN
(
SELECT fc_id_client
FROM
feature_client
INNER JOIN
feature ON
fc_id = id_feature
WHERE id_feature = 8
)

Related

How to cross join tables from multiple servers?

I'm working on a project to create a table that pull information from my local server and 2 online servers. The 2 online servers are both linked with my local server. I only have ability to read from the online servers and the data is to large for me to create a duplicate.
I built some code that would work on Management Studio, however when I place those code into SSRS, I got message that says one of my table already exists. I tried to put a drop table clause in front of that, but then I got message for the next table down the line already existed. And if I pull drop statement for every table, I got a error message for Timeout expired when refresh the fields.
SELECT s.SiteID, s.[StoreName], cf.CustomerID, , cf.AccountNumber, cf.AccountStatus,
cf.Store_ID, cf.InstitutionID, cf.TransactionTime, cf.Comment
INTO #Report_Table1
FROM dbo.View_GetCustomerInfo cf
LEFT JOIN dbo.Store_Table s ON cf.Store_ID = s.Store_ID
;
SELECT t.*, cl.SaleAmount
INTO #Report_Table2
FROM #Report_Table1 t
LEFT JOIN OnlineServe01.Views.dbo.SaleUpdate su
ON t.CustomerID = cl.CustomerID AND t.Store_ID = cl.Store_ID AND [Status] = 'A'
;
SELECT InstitutionID, Source_ID, BankName
INTO #Report_BankName
FROM OnlineServe01.Views.dbo.InstitutionInfo bn
WHERE InstitutionID IN (
SELECT InstitutionID FROM #Report_Table2)
;
SELECT df.*, bn.BankName
INTO #Report_Table3
FROM #Report_Table2 t
LEFT JOIN #Report_BankName bn ON df.InstitutionID = bn.InstitutionID AND df.Store_ID = bn.Store_ID
;
SELECT StoreName, SiteID, CustomerID, SaleAmount
, BankName, AccountNumber, AccountStatus, TransactionTime, Comment
INTO #Report_Table4
FROM #Report_Table3 t
;
SELECT *
INTO #Report_PlayerName
FROM (
SELECT DISTINCT CustomerID, FirstName, LastName,
Dense_Rank () OVER (Partition by CustomerID ORDER BY FirstName) AS Rnk
FROM OnlineServe02.CustomerManagement.dbo.CustomerName
WHERE PreferredName = 0
AND CustomerID IN (SELECT DISTINCT CustomerID FROM #Report_Table4)
) a
WHERE Rnk = 1
;
SELECT t.*, pn.LastName, pn.FirstName, ca.Deposited, ca.Used, ca.InTransit, ca.Available
FROM #Report_Table4 t
LEFT JOIN OnlineServe02.CustomerManagement.dbo.AccountActivity ca
ON t.CustomerID = ca.CustomerID AND t.SiteID = ca.SiteID
LEFT JOIN #Report_PlayerName pn ON t.CustomerID = pn.CustomerID
;

SQL Join with 2 conditions same column but different data names

I need to join 2 tables using 2 columns as identifiers,
Reference and UAP
TABLE 1
Reference
UAP
Week 1
Week 2
Table 2
Reference
UAP
Stock
Here is the problem with data on both tables in UAP column
Table 1 Table 2
UAP1 M1
UAP2 M2
UAP3 M3
UAP4 M4
UAP5 M5
UAP6 M6
UAPP PROTOS
EXT EXTR
the UAPS are the same but name is just different
I have no control over the data i'm getting, it's a IBM DB2 remote server
I tried a local table to join but i want to avoid that 'cause of the performance impact (30+ seconds)
So far my query is this
SELECT
*
FROM OPENQUERY(MACPAC,
'SELECT
P.Referencia,
P.UAP,
P.W01,
P.W02,
S.Stock
FROM AUTO.D805DATPOR.Production AS P
INNER JOIN AUTO.D805DATPOR.Stock S
ON S.Reference = S.Reference
WHERE (P.Reference Not Like ''FS%'')
ORDER BY Reference')
well of course the ideal would be
SELECT
*
FROM OPENQUERY(MACPAC,
'SELECT
P.Referencia,
P.UAP,
P.W01,
P.W02,
S.Stock
FROM AUTO.D805DATPOR.Production AS P
INNER JOIN AUTO.D805DATPOR.Stock S
ON P.Reference = S.Reference AND P.UAP = S.UAP
WHERE (P.Reference Not Like ''FS%'')
ORDER BY Reference')
but it does not work cause different names... Is there a way to make this happen without a local join table that will slow my query by several seconds?
Here is the output of these queries individually
This is the production table
This is the stock table
the output should show me the Stock on the production table by Reference and UAP
EDIT
Sorry for confusion the remote server is IBM DB2. This was an error of my coworker that said it was coming from oracle--
Cheers for correct answer from #Sergey Menshov.
SELECT
Reference,
UAP,
W01,
W02
FROM OPENQUERY(MACPAC,
'SELECT
P.Reference,
P.UAP,
P.W01,
P.W02
FROM AUTO.D805DATPOR.Production AS P
LEFT JOIN AUTO.D805DATPOR.Stock S
ON P.Reference = S.Reference AND
S.UAP =
CASE P.UAP
WHEN ''UAP1'' THEN ''M1''
WHEN ''UAP2'' THEN ''M2''
WHEN ''UAP3'' THEN ''M3''
WHEN ''UAP4'' THEN ''M4''
WHEN ''UAP5'' THEN ''M5''
WHEN ''UAP6'' THEN ''M6''
WHEN ''UAPP'' THEN ''PROTOS''
WHEN ''EXT'' THEN ''EXTR''
END
WHERE (P.Reference Not Like ''FS%'')
ORDER BY Reference DESC')
another method which gives error in UAP1 not a column in table L that might work using dual table for DB2
SELECT
Reference,
UAP,
W01,
W02
FROM OPENQUERY(MACPAC,
'SELECT
P.Reference,
P.UAP,
P.W01,
P.W02
FROM AUTO.D805DATPOR.Production AS P
JOIN
(
SELECT ''UAP1'' AS UAP1, ''M1'' AS UAP2 FROM sysibm.sysdummy1
UNION ALL SELECT ''UAP2'',''M2'' FROM sysibm.sysdummy1
UNION ALL SELECT ''UAP3'',''M3'' FROM sysibm.sysdummy1
UNION ALL SELECT ''UAP4'',''M4'' FROM sysibm.sysdummy1
UNION ALL SELECT ''UAP5'',''M5'' FROM sysibm.sysdummy1
UNION ALL SELECT ''UAP6'',''M6'' FROM sysibm.sysdummy1
UNION ALL SELECT ''UAPP'',''PROTOS'' FROM sysibm.sysdummy1
UNION ALL SELECT ''EXT'',''EXTR'' FROM sysibm.sysdummy1
) L
ON P.UAP = L.UAP1
INNER JOIN AUTO.D805DATPOR.Stock S
ON P.Reference = S.Reference AND S.UAP = L.UAP2
WHERE (P.Reference Not Like ''FS%'')
ORDER BY Reference DESC')
Try to use a link-subquery:
FROM AUTO.D805DATPOR.Production AS P
JOIN
(
SELECT ''UAP1'' AS UAP1,''M1'' AS UAP2 FROM DUAL
UNION ALL SELECT ''UAP2'',''M2'' FROM DUAL
UNION ALL SELECT ''UAP3'',''M3'' FROM DUAL
UNION ALL SELECT ''UAP4'',''M4'' FROM DUAL
UNION ALL SELECT ''UAP5'',''M5'' FROM DUAL
UNION ALL SELECT ''UAP6'',''M6'' FROM DUAL
UNION ALL SELECT ''UAPP'',''PROTOS'' FROM DUAL
UNION ALL SELECT ''EXT'',''EXTR'' FROM DUAL
) L
ON P.UAP=L.UAP1 -- !!!
INNER JOIN AUTO.D805DATPOR.Stock S
ON P.Reference = S.Reference AND S.UAP=L.UAP2 -- !!!
Or you can create a link-table in the Oracle and then use it in your query.
I think it'll be better because you can use it in other queries and insert there a new combinations.
Pseudo code:
CREATE TABLE UAP_LINK(
UAP1 VARCHAR2(20) NOT NULL,
UAP2 VARCHAR2(20) NOT NULL,
PRIMARY KEY(UAP1),
UNIQUE(UAP2)
)
INSERT UAP_LINK VALUES
UAP1, M1
UAP2, M2
UAP3, M3
UAP4, M4
UAP5, M5
UAP6, M6
UAPP, PROTOS
EXT , EXTR
One more variant with CASE:
FROM AUTO.D805DATPOR.Production AS P
INNER JOIN AUTO.D805DATPOR.Stock S
ON P.Reference = S.Reference
AND S.UAP=
CASE P.UAP
WHEN ''UAP1'' THEN ''M1''
WHEN ''UAP2'' THEN ''M2''
WHEN ''UAP3'' THEN ''M3''
WHEN ''UAP4'' THEN ''M4''
WHEN ''UAP5'' THEN ''M5''
WHEN ''UAP6'' THEN ''M6''
WHEN ''UAPP'' THEN ''PROTOS''
WHEN ''EXT'' THEN ''EXTR''
END

Converting Oracle Query into T-SQL query using WITH

I have a query from an old database that we converting into T-SQL, but having issues using CTE:
Original Query in Oracle:
select company_name, display_name, active_flag, naic_code, group_number, alien_code, fein,
status_desc, status_detail_desc, due_to_merger_flag, co_code, to_char(status_date, 'MM/DD/YYYY')
Inactive_Date, active_flag from
(select nm.COMPANY_NAME, cmp.recordid_number, orgtp.display_name, cmp.active_flag,
cmp.naic_code, grpnm.group_number, cmp.alien_code, cmp.fein, st.status_desc, stdt.status_detail_desc,
storgjn.due_to_merger_flag, storgjn.co_code, storgjn.status_date, st.active_flag as activestatus,
max(storgjn.status_date) over (partition by cmp.recordid_number, orgtp.display_name) max_status_date
from aip.co_company cmp join aip.CO_NAME nm on cmp.COMPANY_ID = nm.company_id and nm.active_flag = 1
left outer join aip.co_company_group_jn cmpgrpjn on nm.COMPANY_ID = cmpgrpjn.company_id and cmpgrpjn.active_flag = 1
left outer join aip.co_group_name grpnm on cmpgrpjn.group_id = grpnm.group_id and grpnm.active_flag = 1
join aip.co_org org on cmp.COMPANY_ID = org.company_id
join aip.co_org_type orgtp on org.org_type_id = orgtp.org_type_id
join aip.co_status_org_jn storgjn on org.org_id = storgjn.org_id
join aip.co_status_detail stdt on storgjn.status_detail_id = stdt.status_detail_id
join aip.co_status st on stdt.status_id = st.status_id
WHERE cmp.recordid_number = '10632' AND
stdt.status_detail_desc <> 'Record Begin Date')
WHERE status_date = max_status_date
And converting into T-SQl im using:
WITH YOURCTE(WHATEVA) AS
(
SELECT nm.COMPANY_NAME, cmp.recordid_number, orgtp.display_name, cmp.active_flag,
cmp.naic_code, grpnm.group_number, cmp.alien_code, cmp.fein, st.status_desc, stdt.status_detail_desc,
storgjn.due_to_merger_flag, storgjn.co_code, storgjn.status_date, st.active_flag as activestatus,
max(storgjn.status_date) over (partition by cmp.recordid_number, orgtp.display_name) max_status_date
from aip.co_company cmp join aip.CO_NAME nm on cmp.COMPANY_ID = nm.company_id and nm.active_flag = 1
left outer join aip.co_company_group_jn cmpgrpjn on nm.COMPANY_ID = cmpgrpjn.company_id and cmpgrpjn.active_flag = 1
left outer join aip.co_group_name grpnm on cmpgrpjn.group_id = grpnm.group_id and grpnm.active_flag = 1
join aip.co_org org on cmp.COMPANY_ID = org.company_id
join aip.co_org_type orgtp on org.org_type_id = orgtp.org_type_id
join aip.co_status_org_jn storgjn on org.org_id = storgjn.org_id
join aip.co_status_detail stdt on storgjn.status_detail_id = stdt.status_detail_id
join aip.co_status st on stdt.status_id = st.status_id
WHERE cmp.recordid_number = '10632' AND
stdt.status_detail_desc <> 'Record Begin Date'
)
select company_name, display_name, active_flag, naic_code, group_number, alien_code, fein,
status_desc, status_detail_desc, due_to_merger_flag, co_code, CONVERT(VARCHAR(10),status_date,120) AS Inactive_Date,
active_flag
FROM YOURCTE
WHERE status_date = max_status_date
But I get the following error :
Msg 8158, Level 16, State 1, Line 2
'YOURCTE' has more columns than were specified in the column list.
The reason i have more columns in my cte is because I'm using the recordid_number column to bring other data for where conditioning. I will appreciate some help, thank you.
Either replace "WHATEVA" with a complete list of the column aliases you want to use, or remove it and let the original column names stand.
Inherit
;WITH YOURCTE AS
(...
Explicit
;WITH YOURCTE (COMPANY_NAME, recordid_number, ...) AS
(...

Create and execute stored procedure in SQL Server

I have four tables:
dbo.Projects (id, ProjectName, Areas, PaymentSystem, Districts.id, purpose.id, types.id, etc)
dbo.Districts(id, DistrictsName)
dbo.Purpose (id, PurposeName) - has residential & commercial
dbo.Types (id, typName)
I want to select DistrictsName where PurposeName = 'residential'
I tried this procedure :
CREATE PROCEDURE [dbo].[SearchResidentialProjects]
AS
SELECT
dbo.Projects.ID,
dbo.Districts.DistrictName,
dbo.Purpose.PurposeName
FROM
dbo.Projects
INNER JOIN
dbo.Purpose ON dbo.Projects.PurposeID = dbo.Purpose.ID
INNER JOIN
dbo.Districts ON dbo.Projects.DistrictID = dbo.Districts.ID
WHERE
dbo.Purpose.PurposeName = N'Residential'
this is the result from this procedure:
ID DistrictsName PurposeName
1 District1 residential
2 District1 residential
3 District2 residential
4 District2 residential
i want display the DistrictsName without duplicate or with different values , i a have also one more project per district in projects records . this what i want to display :
ID DistrictsName PurposeName
1 District1 residential
2 District2 residential
how i get this result ,
any help is appreciated.
Why do people use stored procedures when views are much more appropriate? I have never understood this. It seems peculiar to SQL Server users.
In any case, you can do what you want with aggregation:
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as id,
d.DistrictName, p.PurposeName
FROM dbo.Projects pr INNER JOIN
dbo.Purpose pu
ON pr.PurposeID = pu.ID INNER JOIN
dbo.Districts d
ON pr.DistrictID = d.ID
WHERE pu.PurposeName = N'Residential'
GROUP BY d.DistrictName, p.PurposeName;
The use of table aliases makes the query much easier to write and to read.
In addition, I don't understand the id column being output. Why would you want to construct a new id? In any case, that is what your data suggests.
Use DISTINCT statement for removing the duplicates:
CREATE PROCEDURE [dbo].[SearchResidentialProjects]
AS
SELECT DISTINCT
dbo.Projects.ID,
dbo.Districts.DistrictName,
dbo.Purpose.PurposeName
FROM
dbo.Projects
INNER JOIN
dbo.Purpose ON dbo.Projects.PurposeID = dbo.Purpose.ID
INNER JOIN
dbo.Districts ON dbo.Projects.DistrictID = dbo.Districts.ID
WHERE
dbo.Purpose.PurposeName = N'Residential'

T-SQL: Same fields using multiple joins

I reviewed similar questions but could not find an answer to my specific quandry. I'm working with SQL Server 2008 (T-SQL in SQL Server Management Studio) (but much more used to Oracle and Crystal Reports).
Simplified scenario:
Table Customer
customerID (pk)...
Table InsuranceCoverage
customerID (composite pk)
line (composite pk)
insCompanyID (fk)
insPlanID (fk)
Table InsuranceCompany
insCompanyID
insCompanyName
insCompanyAddr
Table InsurancePlan
insPlanID
insPlanName
insPlanClass
I need a report that basically returns the following on one row:
A few columns from Customer
Insurance 1 - columns from InsuranceCompany and InsurancePlan tables where InsuranceCoverage.line = 1
Insurance 2 - columns from InsuranceCompany and InsurancePlan tables where InsuranceCoverage.line = 2
Insurance 3 - columns from InsuranceCompany and InsurancePlan tables where InsuranceCoverage.line = 3
I feel very stupid not being able to figure this out. One customer might have up to three insurances. This would be easy to write multiple queries for, but I've got to get it set up so it can run automatically 1x/month. I've used the same table multiple times in the same report by using aliases on the joins before, but that won't work here because of the InsuranceCoverage.line criteria, right? Is a subquery in the from clause the answer?
Something like this?
SELECT
c.CustomerID,
cov1.*,
cov2.*,
cov3.*,
insco1.insCompanyName as insCompanyName1,
insco2.insCompanyName as insCompanyName2,
insco3.insCompanyName as insCompanyName3,
etc...
FROM
Customer c
LEFT OUTER JOIN InsuranceCoverage cov1 on cov1.CustomerID = c.CustomerID AND cov1.line = 1
LEFT OUTER JOIN InsuranceCoverage cov2 on cov2.CustomerID = c.CustomerID AND cov2.line = 2
LEFT OUTER JOIN InsuranceCoverage cov3 on cov3.CustomerID = c.CustomerID AND cov3.line = 3
JOIN InsuranceCompany insco1 on insco1.insCompanyID = cov1.insCompanyID
JOIN InsuranceCompany insco2 on insco2.insCompanyID = cov2.insCompanyID
JOIN InsuranceCompany insco3 on insco3.insCompanyID = cov3.insCompanyID
JOIN InsurancePlan inspl1 on inspl1.insPlanID = cov1.insPlanID
JOIN InsurancePlan inspl2 on inspl2.insPlanID = cov2.insPlanID
JOIN InsurancePlan inspl3 on inspl3.insPlanID = cov3.insPlanID
I set up some table variables to show that this query works. You'll need to replace them with the real table and column names. I believe something like this would work for you:
DECLARE #Customer TABLE (CustomerId INT)
DECLARE #InsuranceCoverage TABLE
(
CustomerId INT
, Line INT
, InsuranceCompanyId INT
, InsurancePlanId INT
)
DECLARE #InsuranceCompany TABLE
(
Id INT
, Name VARCHAR(100)
, Addr VARCHAR(100)
)
DECLARE #InsurancePlan TABLE
(
Id INT
, Name VARCHAR(100)
, Class VARCHAR(100)
)
SELECT
C.* -- Customer colums.
-- Insurance1 columns.
, ICmp1.*
, IP1.*
-- Insurance2 columns.
, ICmp2.*
, IP2.*
-- Insurance3 columns.
, ICmp3.*
, IP3.*
FROM
#Customer C
LEFT JOIN #InsuranceCoverage ICov1
INNER JOIN #InsuranceCompany ICmp1
ON ICmp1.Id = ICov1.InsuranceCompanyId
INNER JOIN #InsurancePlan IP1
ON IP1.Id = ICov1.InsurancePlanId
ON ICov1.CustomerId = C.CustomerId
AND ICov1.Line = 1
LEFT JOIN #InsuranceCoverage ICov2
INNER JOIN #InsuranceCompany ICmp2
ON ICmp2.Id = ICov2.InsuranceCompanyId
INNER JOIN #InsurancePlan IP2
ON IP2.Id = ICov2.InsurancePlanId
ON ICov2.CustomerId = C.CustomerId
AND ICov2.Line = 2
LEFT JOIN #InsuranceCoverage ICov3
INNER JOIN #InsuranceCompany ICmp3
ON ICmp3.Id = ICov3.InsuranceCompanyId
INNER JOIN #InsurancePlan IP3
ON IP3.Id = ICov3.InsurancePlanId
ON ICov3.CustomerId = C.CustomerId
AND ICov3.Line = 3
you can do a union of 2, 3, 4 as a derived table and join 1 with that, like...
select t1.a,t1.b,t1.c, t2.d, t2.e, t2.f from customer t1,
(select fk, d as d, 0 as e, 0 as f from ic where line=1
union select fk, 0, e, 0 from ic where line=2
union select fk, 0, 0, f from ic where line=3) as t2
where t1.pk = t2. fk
something like that
edit: oh, right, if they can have no insurance then change it to a left join like ...
select t1.a,t1.b,t1.c, t2.d, t2.e, t2.f from customer t1 left join
(select fk, d as d, 0 as e, 0 as f from ic where line=1
union select fk, 0, e, 0 from ic where line=2
union select fk, 0, 0, f from ic where line=3) as t2
on t1.pk = t2.fk
... or something like that :)

Resources