开发者

SQL query select from table and group on other column

I'm phrasing the question title poorly as I'm not sure what to call what I'm trying to do but it really sh开发者_开发知识库ould be simple.

I've a link / join table with two ID columns. I want to run a check before saving new rows to the table.

The user can save attributes through a webpage but I need to check that the same combination doesn't exist before saving it. With one record it's easy as obviously you just check if that attributeId is already in the table, if it is don't allow them to save it again.

However, if the user chooses a combination of that attribute and another one then they should be allowed to save it.

Here's an image of what I mean:

SQL query select from table and group on other column

So if a user now tried to save an attribute with ID of 1 it will stop them, but I need it to also stop them if they tried ID's of 1, 10 so long as both 1 and 10 had the same productAttributeId.

I'm confusing this in my explanation but I'm hoping the image will clarify what I need to do.

This should be simple so I presume I'm missing something.


If I understand the question properly, you want to prevent the combination of AttributeId and ProductAttributeId from being reused. If that's the case, simply make them a combined primary key, which is by nature UNIQUE.

If that's not feasible, create a stored procedure that runs a query against the join for instances of the AttributeId. If the query returns 0 instances, insert the row.

Here's some light code to present the idea (may need to be modified to work with your database):

SELECT COUNT(1) FROM MyJoinTable WHERE AttributeId = @RequestedID
IF @@ROWCOUNT = 0
BEGIN
   INSERT INTO MyJoinTable ...
END


You can control your inserts via a stored procedure. My understanding is that

  1. users can select a combination of Attributes, such as
    • just 1
    • 1 and 10 together
    • 1,4,5,10 (4 attributes)

These need to enter the table as a single "batch" against a (new?) productAttributeId

So if (1,10) was chosen, this needs to be blocked because 1-2 and 10-2 already exist.

What I suggest

The stored procedure should take the attributes as a single list, e.g. '1,2,3' (comma separated, no spaces, just integers)

You can then use a string splitting UDF or an inline XML trick (as shown below) to break it into rows of a derived table.

Test table

create table attrib (attributeid int, productattributeid int)
insert attrib select 1,1
insert attrib select 1,2
insert attrib select 10,2

Here I use a variable, but you can incorporate as a SP input param

declare @t nvarchar(max) set @t = '1,2,10'

select top(1)
  t.productattributeid,
  count(t.productattributeid) count_attrib,
  count(*) over () count_input
from (select convert(xml,'<a>' + replace(@t,',','</a><a>') + '</a>') x) x
cross apply x.x.nodes('a') n(c)
cross apply (select n.c.value('.','int')) a(attributeid)
left join attrib t on t.attributeid = a.attributeid
group by t.productattributeid
order by countrows desc

Output

productattributeid     count_attrib     count_input
2                      2                3
  1. The 1st column gives you the productattributeid that has the most matches
  2. The 2nd column gives you how many attributes were matched using the same productattributeid
  3. The 3rd column is how many attributes exist in the input

If you compare the last 2 columns and the counts

  1. match - you can use the productattributeid to attach to the product which has all these attributes
  2. don't match - then you need to do an insert to create a new combination
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜