Max value in a many-to-many relationship - sql

I'm using SQL Server 2008 and I have 3 tables, x, y and z. y exists to create a many-to-many relationship between x and z.
x y z
-- -- --
id xid id
zid sort
All of the above fields are int.
I want to find the best-performing method (excluding denormalising) of finding the z with the highest sort for any x, and return all fields from all three tables.
Sample data:
x: id
--
1
2
y: xid zid
--- ---
1 1
1 2
1 3
2 2
z: id sort
-- ----
1 5
2 10
3 25
Result set should be
xid zid
--- ---
1 3
2 2
Note that if more than one z exists with the same highest sort value, then I still only want one row per x.
Note also that in my real-world situation, there are other fields in all three tables which I will need in my result set.

One method is with a sub query. This however is only good for getting the ID of Z. If you need more/all columns from both x and z tables then this is not the best solution.
SELECT
x.id,
(
SELECT TOP 1
z.zid
FROM
y
INNER JOIN
z
ON
z.id = y.zid
WHERE
y.xid = x.id
ORDER BY
z.sort DESC
)
FROM
x
This is how you can do it and return all the data from all the tables.
SELECT
*
FROM
x
INNER JOIN
y
ON
y.xid = x.id
AND
y.zid =
(
SELECT TOP 1
z2.zid
FROM
y y2
INNER JOIN
z z2
ON
z2.id = y2.zid
WHERE
y2.xid = x.id
ORDER BY
z2.sort DESC
)
INNER JOIN
z
ON
z.id = y.zid

select xid,max(zid) as zid from y
group by xid

select xid, zid /* columns from x; and columns from y or z taken from q */
from (select y.xid, y.zid, /* columns from y or z */
row_number() over(partition by y.xid order by z.sort desc) r
from y
join z on z.id = y.zid
) q
join x on x.id = q.xid
where r = 1

Related

Group and include all categories in SQL

I need to select all groups in a table for each category, even if that group is missing for a given category (and put 0 or NULL as value)
I need to do this via a SQL query (Impala).
An example is reported below (basically I need to dynamically display also the last row in the second table).
Category Group Amount Category Group Amount
+--------------------------------+ +--------------------------------+
A X 1 A X 1
A Y 2 A Y 2
A Z 5 -> A Z 5
B X 2 B X 2
B Y 3 B Y 3
B Z 0
Anyone knows how to achieve this? Thanks!
You need a Cross Join of the categories and the groups first and then a Left Join:
select c.category, g.group, coalesce(amount, 0)
from
( -- all categories
select distinct Category from tab
) as c
cross join -- create all possible combinations
( -- all groups
select distinct group from tab
) as g
left join tab as a -- now join back the amount
on c.category = a.category
and g.group = a.Group

Count duplicate records by using linq

Count duplicate records by using linq
.................................................................................................................................................
Col1 col2
x a
x a
x b
x b
y c
y c
y d
y d
z e
z e
z f
now i want count like follows
x a 2
x b 2
y c 2
y d 2
in linq plese any one assist me
table
.GroupBy(x=>new{x.col1,x.clo2})
.Select(x=>new{ x.key.col1,x.key.col2,x.Count(z=>z.col1)
var Result =
from t in table
group t by new
{
t.col1,
t.col2,
} into gt
select new
{
col1 = gt.Key.col1,
col2 = gt.Key.col2,
count = gt.Count(),
};

SQL: select only data from one column, for which one of the value from second column is x

I have a problem which I can't describe without explaining this on this example:
So there are 2 columns like:
X Y
A 2
A 1
A 3
B 3
C 2
A 1
D 2
B 1
B 3
C 1
A 1
D 3
D 1
and now I would like to select only that data from X, where one of the values from Y is 2.
So my output should look like:
X Y
A 2
A 1
A 3
C 2
A 1
D 2
C 1
A 1
D 3
D 1
because Y=2 for X=B doesn't exist in the main table.
My question is what is the query for this operation? I tried something with CASE WHEN but something didn't fix for me.
Try
SELECT X FROM Table WHERE X IN (SELECT X FROM Table WHERE Y=2)
OR Try
SELECT t1.X FROM Table t1
INNER JOIN Table t2 ON t1.X = t2.X
WHERE t2.Y = 2
Try a subquery:
SELECT X FROM table WHERE X IN (SELECT X FROM table WHERE Y = 2);

Find column from multiple column

I have one question about database query. Please refer below table.
Table : 1
ID Country
1 x
2 y
3 z
4 k
Table : 2
eng fre fre1 fre2
x x
x1 k y t
x2 n z
Output Table
id country
1 x
2 x1
3 x2
4 x1
How to achieve this in Hive?
Thank you so much for help.
You can join three times but it may run slow:
select a.id, coalesce(b.eng, c.eng, d.eng) as Country
from table_1 a
left join table_2 b on a.country=b.fre
left join table_2 c on a.country=c.fre1
left join table_2 d on a.country=d.fre2
;

How to select all products satisfying n numbers of attributeid/attributevalue conditions

I have a Products table and ProductAttributeValues table
Product
-------
ID 1
Name A
ID 2
Name B
ProductAttributeValues
-------
ID 1
ProductID 1
AttributeID 1
Values Z
ID 2
ProductID 1
AttributeID 2 1
Values Y
ID 3
ProductID 1
AttributeID 3 1
Values P
I need to select all products where,
((ProductAttributeValues.attrbuteid = X and ProductAttributeValues.Value = X)
AND (ProductAttributeValues.attrbuteid = X and ProductAttributeValues.Value = X)
AND ............................................................................
AND ............................................................................)
These conditions are dynamic. So it might be 1 or 2 or 3 or so on.
So how to select all products satisfying n numbers of aattributeid/attribute value conditions?
Method 1
Use AttributeValues table multiple times in the join.
SELECT P.*
FROM
Product P
JOIN ProductAttributeValues PA1 ON P.ID = PA1.ProductID AND PA1.AttributeID = X AND PA1.VALUES = X
JOIN ProductAttributeValues PA2 ON P.ID = PA2.ProductID AND PA2.AttributeID = Y AND PA2.VALUES = Y
JOIN ProductAttributeValues PA3 ON P.ID = PA3.ProductID AND PA3.AttributeID = Z AND PA3.VALUES = Z
..........And So on
Method 2
Pivot ProductAttributeValues table with AttributeID and AttributeValues as multiple columns. Now you can easily join your product and ProductAttributeValues to get the data you need.
SELECT *
FROM Product P
JOIN ProductAttributeValuesPivot PAP
ON P.ID = PAP.ProductID
WHERE PAP.AttributeX = X AND PAP.ValueX = X
AND PAP.AttributeY = Y AND PAP.ValueY = Y
PAP.AttributeZ = Z AND PAP.ValueZ = Z
............... And So on
Links for Pivot
Dynamic Pivot Table in SQL Server
Technet Article for PIVOT and UNPIVOT
http://sqlmag.com/t-sql/create-pivoted-tables-3-steps
This is a "set-within-sets" query. I think the most general approach is aggregation with a having caluse:
select productID
from ProductAttributeValues pav
group by productID
having sum(case when ProductAttributeValues.attrbuteid = X and ProductAttributeValues.Value = X
then 1 else 0 end) > 0 and
sum(case when ProductAttributeValues.attrbuteid = Y and ProductAttributeValues.Value = Y
then 1 else 0 end) > 0 and
. . .
Each condition in the having clause counts the number of attributes for each product that match the condition. The overall clause is true when all the conditions have at least one row.