不在同一个表的行内

时间:2016-02-03 13:21:27

标签: mysql sql

我在尝试找出目前需要的查询时遇到了一些困难。

我会尽力解释这种情况并尽可能缩短。

我有一个名为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

我的错误是什么,或者我错过了什么?

感谢您抽出宝贵时间回答。

1 个答案:

答案 0 :(得分: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循环并按'description desc'排序..那样'Pencil(绿色)'在'Pencil'之前出现

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循环获取Max并设置变量

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, @retvalOUT=@Count 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”值然后你得到你想要什么