Joining two tables and getting values - sql

I have two config tables. The structure is as below:
Table 1: Client_Config
id, name, value, type, description
Table 2: App_Config
name, value, type, description
I want to get name and value from Client_config table where id = #id.
I also want to get name and values from App_config for rows where there are no entries(matched with name) in client_config. Values for the same name can be different in both the tables.
eg:
Values in Client_Config
1, testName, testValue, testType, testDescription
1, testName1, testValue1, testType1, testDescription1
1, testName2, testValue2, testType2, testDescription2
Values in App_Config
testName, testValue1, testType, testDescription
testName1, testValue1, testType1, testDescription1
testName2, testValue2, testType2, testDescription2
testName3, testValue3, testType3, testDescription3
In the result set I need the following rows:
1, testName, testValue, testType, testDescription
1, testName1, testValue1, testType1, testDescription1
1, testName2, testValue2, testType2, testDescription2
NULL, testName3, testValue3, testType3, testDescription3

You can try a query like below
select
c.id, a.name, a.value, a.type, a.description
from App_Config a
left join
(
select * from Client_Config where id=#id
)c
on c.name=a.name
Explanation: We need all rows from app_config and corresponding id from client_config. So we do a **LEFT JOIN** from A to C. The C result set however must contain rows from a particular #id only so we sneak in a WHERE clause in the C set
Sql fiddle demo link : http://sqlfiddle.com/#!6/44659/4

You can do it using a left join:
SELECT t.id, s.name, s.value, s.type, s.description
FROM App_Config s
LEFT JOIN Client_Config t
ON(t.name = s.name and t.id = #id)

You can do it using a UNION ALL operation:
DECLARE #id INT = 1
SELECT id, name, value, type, description
FROM Client_Config
WHERE id = #id
UNION ALL
SELECT NULL, name, value, type, description
FROM App_Config AS ac
WHERE NOT EXISTS (SELECT 1
FROM Client_Config AS cc
WHERE cc.name = ac.name AND cc.id = #id)
Demo here

With a Left Join you get all the rows from the left table and all the corresponding rows from the right table. If there is no matching information, then the columns of the right table will be NULL.
Take a look at this useful diagram:
SQL Join Diagrams
In particular, your query can be something like this:
SELECT c.id, a.name, a.value, a.type, a.description
FROM App_Config a
LEFT JOIN Client_Config c
ON c.name = a.name
WHERE c.id = #id

Related

minus two tables with primary key

I have sql database with tables:
sc: s_id, m_id
s: id, name
m: id, name
sc_standart: s_id, m_id
s_standart: id, name
m_standart: id, name
sc.s_id is from s.id, sc.m_id is from m.id, sc_standart.s_id is from s_standart.id, sc_standart.m_id is from m_standart.id.
I should set m_id=null for all lines from sc which are not exist in sc_standart.
I had already written:
SELECT s.name, m.name
FROM s
JOIN sc
ON s.id=sc.s_id
JOIN m
ON m.id=sc.m_id
MINUS
SELECT s_standart.name, m_standart.name
FROM s_standart
JOIN sc_standart
ON s_standart.id=sc_standart.s_id
JOIN m_standart
ON m_standart.id=sc_standart.m_id
So I should update (s_id, m_id) lines relevant to (s.name, m.name) from the select above.
It looks like you could just do it as:
update sc
set m_id = null
where not exists
( select 1 from sc_standart s
where s.m_id = sc.m_id )
Or using minus:
update sc
set m_id = null
where m_id in
( select m_id from sc
minus
select m_id from sc_standart )
However, I might be missing something as I couldn't see how the other four tables were related to your question.

How to join three tables with distinct

I'm trying to join three tables to pull back a list of distinct blog posts with associated assets (images etc) but I keep coming up a cropper. The three tablets are tblBlog, tblAssetLink and tblAssets. The Blog tablet hold the blog, the asset table holds the assets and the Assetlink table links the two together.
tblBlog.BID is the PK in blog, tblAssets.AID is the PK in Assets.
This query works but pulls back multiple posts for the same record. I've tried to use select distinct and group by and even union but as my knowledge is pretty poor with SQL - they all error.
I'd like to also discount any assets that are marked as deleted (tblAssets.Deleted = true) but not hide the associated Blog post (if that's not marked as deleted). If anyone can help - it would be much appreciated! Thanks.
Here's my query so far....
SELECT dbo.tblBlog.BID,
dbo.tblBlog.DateAdded,
dbo.tblBlog.PMonthName,
dbo.tblBlog.PDay,
dbo.tblBlog.Header,
dbo.tblBlog.AddedBy,
dbo.tblBlog.PContent,
dbo.tblBlog.Category,
dbo.tblBlog.Deleted,
dbo.tblBlog.Intro,
dbo.tblBlog.Tags,
dbo.tblAssets.Name,
dbo.tblAssets.Description,
dbo.tblAssets.Location,
dbo.tblAssets.Deleted AS Expr1,
dbo.tblAssetLink.Priority
FROM dbo.tblBlog
LEFT OUTER JOIN dbo.tblAssetLink
ON dbo.tblBlog.BID = dbo.tblAssetLink.BID
LEFT OUTER JOIN dbo.tblAssets
ON dbo.tblAssetLink.AID = dbo.tblAssets.AID
WHERE ( dbo.tblBlog.Deleted = 'False' )
ORDER BY dbo.tblAssetLink.Priority, tblBlog.DateAdded DESC
EDIT
Changed the Where and the order by....
Expected output:
tblBlog.BID = 123
tblBlog.DateAdded = 12/04/2015
tblBlog.Header = This is a header
tblBlog.AddedBy = Persons name
tblBlog.PContent = *text*
tblBlog.Category = Category name
tblBlog.Deleted = False
tblBlog.Intro = *text*
tblBlog.Tags = Tag, Tag, Tag
tblAssets.Name = some.jpg
tblAssets.Description = Asset desc
tblAssets.Location = Location name
tblAssets.Priority = True
Use OUTER APPLY:
DECLARE #b TABLE ( BID INT )
DECLARE #a TABLE ( AID INT )
DECLARE #ba TABLE
(
BID INT ,
AID INT ,
Priority INT
)
INSERT INTO #b
VALUES ( 1 ),
( 2 )
INSERT INTO #a
VALUES ( 1 ),
( 2 ),
( 3 ),
( 4 )
INSERT INTO #ba
VALUES ( 1, 1, 1 ),
( 1, 2, 2 ),
( 2, 1, 1 ),
( 2, 2, 2 )
SELECT *
FROM #b b
OUTER APPLY ( SELECT TOP 1
a.*
FROM #ba ba
JOIN #a a ON a.AID = ba.AID
WHERE ba.BID = b.BID
ORDER BY Priority
) o
Output:
BID AID
1 1
2 1
Something like:
SELECT b.BID ,
b.DateAdded ,
b.PMonthName ,
b.PDay ,
b.Header ,
b.AddedBy ,
b.PContent ,
b.Category ,
b.Deleted ,
b.Intro ,
b.Tags ,
o.Name ,
o.Description ,
o.Location ,
o.Deleted AS Expr1 ,
o.Priority
FROM dbo.tblBlog b
OUTER APPLY ( SELECT TOP 1
a.* ,
al.Priority
FROM dbo.tblAssetLink al
JOIN dbo.tblAssets a ON al.AID = a.AID
WHERE b.BID = al.BID
ORDER BY al.Priority
) o
WHERE b.Deleted = 'False'
You cannot join three tables unless they all have the same attribute. It would work if all tables had BID, but the second join is trying to join AID. Which wont work. They all have to have BID.
Based on your comments
i would like to get is just one asset per blog post (top one ordered
by Priority)
You can change your query as following. I suggest changing the join with dbo.tblAssetLink to filtered one, which contains only one (highest priority) link for every blog.
SELECT dbo.tblBlog.BID,
dbo.tblBlog.DateAdded,
dbo.tblBlog.PMonthName,
dbo.tblBlog.PDay,
dbo.tblBlog.Header,
dbo.tblBlog.AddedBy,
dbo.tblBlog.PContent,
dbo.tblBlog.Category,
dbo.tblBlog.Deleted,
dbo.tblBlog.Intro,
dbo.tblBlog.Tags,
dbo.tblAssets.Name,
dbo.tblAssets.Description,
dbo.tblAssets.Location,
dbo.tblAssets.Deleted AS Expr1,
dbo.tblAssetLink.Priority
FROM dbo.tblBlog
LEFT OUTER JOIN
(SELECT BID, AID,
ROW_NUMBER() OVER (PARTITION BY BID ORDER BY [Priority] DESC) as N
FROM dbo.tblAssetLink) AS filteredAssetLink
ON dbo.tblBlog.BID = filteredAssetLink.BID
LEFT OUTER JOIN dbo.tblAssets
ON filteredAssetLink.AID = dbo.tblAssets.AID
WHERE dbo.tblBlog.Deleted = 'False' AND filteredAssetLink.N = 1
ORDER BY tblBlog.DateAdded DESC

Want to fetch the data in the form of a table

I have written this query:
SELECT
d.DetailId,
i.ItemId,
d.fieldId,
d.Fieldvalue,
f.Name
FROM
EntityItemDetails d
inner join EntityItems i
on i.ItemId = d.ItemId
inner join Fields f
on f.Id = d.FieldId
WHERE
i.EntityId = 1
Output is:
DetailId ItemId FieldId FieldValue FieldName
1 1 9 Defect1 Name
2 1 10 abcdef Description
5 1 11 testing123 Status
I want result in this way:
Name Description Status
TestField abcdef testing123
Please suggest how to get this result by writing a query in sql.
What you want is called pivoting, and starting from SQL Server 2005, you can use a standard syntax for pivoting in Transact-SQL, with the help of the PIVOT clause.
Your query could be transformed for use with PIVOT like this:
WITH source AS (
/* this CTE is actually your original query */
SELECT
EntityItemDetails.DetailId,
EntityItems.ItemId,
EntityItemDetails.fieldId,
EntityItemDetails.Fieldvalue,
Fields.Name
FROM EntityItemDetails
INNER JOIN EntityItems ON EntityItems.ItemId = EntityItemDetails.ItemId
INNER JOIN Fields ON Fields.Id = EntityItemDetails.FieldId
WHERE EntityItems.EntityId = 1
)
SELECT
ItemId,
Name,
Description,
Status
FROM (
SELECT ItemId, FieldName, FieldValue
FROM source
) s
PIVOT (
MAX(FieldValue) FOR FieldName IN (
Name,
Description,
Status
/* add other possible names as necessary */
)
) p
SELECT
FieldValue,
[Name],
[Description],
[Status]
FROM
myTable -- OR (your posted query) myQuery
PIVOT
(
MIN(FieldValue)
FOR FieldName IN ([Name], [Description], [Status])
) AS myPivot;
Tahnk u so much Andriy M....
with very few changes I could get the desired result. Chenges are as below
WITH source AS (
/* this CTE is actually your original query */
SELECT EntityItemDetails.CreatedDate, EntityItems.EntityItemId,
EntityItemDetails.fieldId,
EntityItemDetails.Fieldvalue,
Fields.Name FieldName FROM EntityItemDetails
INNER JOIN EntityItems ON EntityItems.EntityItemId = EntityItemDetails.EntityItemId
INNER JOIN Fields ON Fields.Id = EntityItemDetails.FieldId WHERE EntityItems.EntityId = 1 and (FieldId=9 or FieldId=10 or FieldId=11) )
SELECT EntityItemId, [Name], [Description], [Status]
FROM ( SELECT EntityItemId, FieldName, FieldValue FROM source ) s
PIVOT ( MAX(FieldValue) FOR FieldName IN ( [Name], [Description], [Status] ) ) p

SQL show records that don't exist in my table variable

I have a table variable that holds orderID, UnitID and OrderServiceId (it is already populated via a query with insert statement).
I then have a query under this that returns 15 columns which also include the OrderId, UnitId, OrderServiceId
I need to only return the rows from this query where the same combination of OrderId, UnitId, and OrderServiceId are not in the table variable.
You can use NOT EXISTS. e.g.
FROM YourQuery q
WHERE NOT EXISTS
(
SELECT * FROM #TableVar t
WHERE t.OrderId = q.OrderId
and t.UnitId = q.UnitId
and t.OrderServiceId=q.OrderServiceId
)
select q.*
from (
MyQuery
) q
left outer join MyTableVariable t on q.ORDERID = t.ORDERID
and q.UNITID= t.UNITID
and q.ORDERSERVICESID = t.ORDERSERVICESID
where t.ORDERID is null
You can use EXCEPT | INTERSECT operators for this (link).
Example:
(select 3,4,1
union all
select 2,4,1)
intersect
(select 1,2,9
union all
select 3,4,1)

Multiple MAX values select using inner join

I have query that work for me only when values in the StakeValue don't repeat.
Basically, I need to select maximum values from SI_STAKES table with their relations from two other tables grouped by internal type.
SELECT a.StakeValue, b.[StakeName], c.[ProviderName]
FROM SI_STAKES AS a
INNER JOIN SI_STAKESTYPES AS b ON a.[StakeTypeID] = b.[ID]
INNER JOIN SI_PROVIDERS AS c ON a.[ProviderID] = c.[ID] WHERE a.[EventID]=6
AND a.[StakeGroupTypeID]=1
AND a.StakeValue IN
(SELECT MAX(d.StakeValue) FROM SI_STAKES AS d
WHERE d.[EventID]=a.[EventID] AND d.[StakeGroupTypeID]=a.[StakeGroupTypeID]
GROUP BY d.[StakeTypeID])
ORDER BY b.[StakeName], a.[StakeValue] DESC
Results for example must be:
[ID] [MaxValue] [StakeTypeID] [ProviderName]
1 1,5 6 provider1
2 3,75 7 provider2
3 7,6 8 provider3
Thank you for your help
There are two problems to solve here.
1) Finding the max values per type. This will get the Max value per StakeType and make sure that we do the exercise only for the wanted events and group type.
SELECT StakeGroupTypeID, EventID, StakeTypeID, MAX(StakeValue) AS MaxStakeValue
FROM SI_STAKES
WHERE Stake.[EventID]=6
AND Stake.[StakeGroupTypeID]=1
GROUP BY StakeGroupTypeID, EventID, StakeTypeID
2) Then we need to get only one return back for that value since it may be present more then once.
Using the Max Value, we must find a unique row for each I usually do this by getting the Max ID is has the added advantage of getting me the most recent entry.
SELECT MAX(SMaxID.ID) AS ID
FROM SI_STAKES AS SMaxID
INNER JOIN (
SELECT StakeGroupTypeID, EventID, StakeTypeID, MAX(StakeValue) AS MaxStakeValue
FROM SI_STAKES
WHERE Stake.[EventID]=6
AND Stake.[StakeGroupTypeID]=1
GROUP BY StakeGroupTypeID, EventID, StakeTypeID
) AS SMaxVal ON SMaxID.StakeTypeID = SMaxVal.StakeTypeID
AND SMaxID.StakeValue = SMaxVal.MaxStakeValue
AND SMaxID.EventID = SMaxVal.EventID
AND SMaxID.StakeGroupTypeID = SMaxVal.StakeGroupTypeID
3) Now that we have the ID's of the rows that we want, we can just get that information.
SELECT Stakes.ID, Stakes.StakeValue, SType.StakeName, SProv.ProviderName
FROM SI_STAKES AS Stakes
INNER JOIN SI_STAKESTYPES AS SType ON Stake.[StakeTypeID] = SType.[ID]
INNER JOIN SI_PROVIDERS AS SProv ON Stake.[ProviderID] = SProv.[ID]
WHERE Stake.ID IN (
SELECT MAX(SMaxID.ID) AS ID
FROM SI_STAKES AS SMaxID
INNER JOIN (
SELECT StakeGroupTypeID, EventID, StakeTypeID, MAX(StakeValue) AS MaxStakeValue
FROM SI_STAKES
WHERE Stake.[EventID]=6
AND Stake.[StakeGroupTypeID]=1
GROUP BY StakeGroupTypeID, EventID, StakeTypeID
) AS SMaxVal ON SMaxID.StakeTypeID = SMaxVal.StakeTypeID
AND SMaxID.StakeValue = SMaxVal.MaxStakeValue
AND SMaxID.EventID = SMaxVal.EventID
AND SMaxID.StakeGroupTypeID = SMaxVal.StakeGroupTypeID
)
You can use the over clause since you're using T-SQL (hopefully 2005+):
select distinct
a.stakevalue,
max(a.stakevalue) over (partition by a.staketypeid) as maxvalue,
b.staketypeid,
c.providername
from
si_stakes a
inner join si_stakestypes b on
a.staketypeid = b.id
inner join si_providers c on
a.providerid = c.id
where
a.eventid = 6
and a.stakegrouptypeid = 1
Essentially, this will find the max a.stakevalue for each a.staketypeid. Using a distinct will return one and only one row. Now, if you wanted to include the min a.id along with it, you could use row_number to accomplish this:
select
s.id,
s.maxvalue,
s.staketypeid,
s.providername
from (
select
row_number() over (order by a.stakevalue desc
partition by a.staketypeid) as rownum,
a.id,
a.stakevalue as maxvalue,
b.staketypeid,
c.providername
from
si_stakes a
inner join si_stakestypes b on
a.staketypeid = b.id
inner join si_providers c on
a.providerid = c.id
where
a.eventid = 6
and a.stakegrouptypeid = 1
) s
where
s.rownum = 1