2016-02-03 18 views
1

我在尝试查找我目前需要的查询时遇到了一些困难。当不在同一张表的同一行内时获得结果

我会尝试尽可能地解释情况并尽可能缩短。

我有一个名为articles_properties的多对多表,它来自两个其他表的组合:文章和属性。这些表具有以下结构,最重要的列和一些示例:

Property table 
------------------------- 
| id | property_name| 
| 1 |  name  | 
| 2 | variations | 
------------------------- 

Article table 
-------------- 
|  id  | 
|  A1  | 
|  A2  | 
|  A3  | 
|  A4  | 
|  A5  | 
-------------- 

Article_properties table 
-------------------------------------------------- 
| article_id | property_id | property_value | 
|  A1  |  1  |  Pencil  | 
|  A1  |  2  |  A2, A3  | 
|  A2  |  1  | Pencil (blue) | 
|  A3  |  1  | Pencil (green) | 
|  A4  |  1  |  Book  | 
|  A5  |  1  | Tennis ball | 
-------------------------------------------------- 

它基本上是你可以看到的。也许唯一不直观的是变体:它是确定文章不同变体的属性。例如,铅笔文章有两个变体:铅笔(蓝色)和铅笔(绿色),用列表property_value中的各自文章ID表示。

现在的问题是,我想从Article_properties表中获取除另一个属性变体内出现的所有文章之外的所有文章。这意味着我想得到如下结果:

Query result 
-------------------------------------------------- 
| article_id | property_id | property_value | 
|  A1  |  1  |  Pencil  | 
|  A1  |  2  |  A2, A3  | 
|  A4  |  1  |  Book  | 
|  A5  |  1  | Tennis ball | 
-------------------------------------------------- 

我该如何做,同时尽可能保持简单和干净?目前,我有以下查询,预期其无法正常工作:

SELECT ap.* FROM article_properties ap 
LEFT JOIN property p ON p.id = ap.property_id 
WHERE (p.property_name = 'name' OR p.property_name = 'variations') 
AND ap.property_value != '' 
AND ap.property_value NOT LIKE CONCAT('%',ap.article_id,'%') 
GROUP BY ap.article_id, ap.property_id 

究竟是什么我的错误或我缺少什么?

谢谢你花时间回答。

+0

你的第一个问题是(明显的)缺乏标准化 – Strawberry

+0

“Article”表与这里的任何东西有什么关系? – Fred

+0

您可能会考虑制作一个“变体”表格“A2,A3”不是有效的变体。 – Strawberry

回答

1

我不太喜欢MySQL ......但问题似乎很有趣,所以我试图用T-SQL来解决它......这就是我如何在T-SQL中实现它...如果你可以将它翻译成MySQL,希望它会对你有好处。

反正这是我做过什么

就在这里建立的数据,是有点相同,您输入

If object_id('tempdb..#temp') is not null drop table #temp 
create table #Temp (ID int, descriptions nvarchar(100)) 
insert into #Temp (ID, descriptions) values (2, 'A2, A3'), 
(1, 'Pencil (blue)'), 
(1, 'Pencil (green)'), 
(1, 'Book'), 
(1, 'Tennis ball'), 
(1, 'Pencil') 

创建tempTables,与ROW_NUMBER只是一个while循环和排序由“描述说明” ..这样‘铅笔(绿色)’之前去‘铅笔’

If object_id('tempdb..#tempWithRowNum') is not null drop table #tempWithRowNum 
    select row_number() over (order by descriptions desc) rownum, 
    * into #tempWithRowNum from #temp t1 

If object_id('tempdb..#Finish') is not null drop table #Finish 
create table #Finish (LastStanding_property nvarchar(100)) 

获取最大的while循环,并设置变量

declare @s int = (select max(rownum) from (
    select row_number() over (order by descriptions desc) rownum, 
* from #temp t1) 
src) 

declare @Thing nvarchar(100) 
declare @cmd nvarchar(max) 
declare @Count int 
declare @ParmDefinition nvarchar(100) 
declare @i int = 1 

这里的逻辑......我只是通过整个表使用一个说明正在运行,如果我得到COUNT(*)高于1,这意味着你有一些类似PROPERTY_VALUE

while @i <= @s 
    begin 

    set @Thing = (select descriptions from #tempWithRowNum where rownum = @i) 

    set @cmd = 'select @retvalOut = count(*) 
        from #temp where descriptions like ''%' + @Thing + '%''' 


    SET @ParmDefinition = N'@retvalOUT int OUTPUT'; 

    EXEC sp_executesql @cmd, @ParmDefinition, @[email protected] OUTPUT; 

    IF @Count = 1 
    begin 
     insert into #Finish (LastStanding_property) values (@Thing) 
    end 
    else 
    begin 
     set @cmd = 'delete from #Finish where LastStanding_property like ''%' + @Thing + '%''' 
     execute (@cmd) 
     insert into #Finish (LastStanding_property) values (@Thing) 
    end 

    set @i = @i + 1 
end 

select * from #Finish 

所以,就像我说的。如果你得到Count(*)高于1 ...意味着你有“Child”属性值...你从#Finish表中删除它们并插入“parent”值,你得到你想要的

相关问题