如何加入“其他”行

时间:2017-03-15 17:06:19

标签: sql-server tsql sql-server-2014

我有两张桌子。一个持有Objects,另一个持有Settings关于每个对象。并非Objects表中的所有行都在Settings表中具有相应的行。 Settings表中有一个特殊的行应该用于“其他”对象。

如何在ObjectsSettings之间创建联接,以便在有一个设置时获得给定设置,如果没有,则获得“其他”设置?

例如,请考虑以下脚本:

CREATE TABLE #Objects (Code nvarchar(20) not null);
CREATE TABLE #Settings (Code nvarchar(20) not null, Value int not null);

INSERT INTO #Objects
VALUES
    ('A'),
    ('B'),
    ('D')

INSERT INTO #Settings
VALUES
    ('A', 1),
    ('B', 2),
    ('C', 3),
    ('Other', 4)

SELECT 
    #Objects.Code,
    #Settings.Value 
FROM
    #Objects
    JOIN #Settings
        ON #Objects.Code = #Settings.Code
        OR #Settings.Code = 'Other'

DROP TABLE #Settings, #Objects

我想要得到这个:

Code | Value
---- | -----
A    | 1
B    | 2
D    | 4

我实际得到的是:

Code  | Value
----- | -----
A     | 1
A     | 4
B     | 2
B     | 4
D     | 4

4 个答案:

答案 0 :(得分:2)

您可以使用APPLY

执行此操作
SELECT o.Code, s.Value
FROM #Objects o
CROSS APPLY (
    SELECT TOP 1 * 
    FROM #Settings s 
    WHERE s.Code = o.Code or s.Code = 'Other' 
    ORDER BY case when s.Code = o.Code then 0 else 1 end
) s

为了好玩:来自GurvjyaoSqlZim的答案的混合体,它们都是同一基本主题的变体:

SELECT o.Code, s2.Value
FROM #Objects o
LEFT JOIN #Settings s1 on s1.Code = o.Code
INNER JOIN #Settings s2 on s2.Code = coalesce(s1.Code, 'Other')

到目前为止,这种方法(LEFT JOIN + INNER JOIN ON COALESCE())是我最喜欢的选择。

请注意,这仅适用于每个对象记录只能有一个设置记录的情况。如果有变化,则APPLY回答仍然有效,但此处的其他答案可能无效。

答案 1 :(得分:1)

使用left join获取null o.Code#Settings不匹配的地方value ,并使用coalesce()返回指定的替换#Settings s.Value null coalesce时来自select o.Code , coalesce(s.Value,x.Value) as Value from #Objects o left join #Settings s on o.Code = s.Code cross join ( select top 1 value from #Settings where Code = 'Other' ) x

您可以使用isnull()代替+------+-------+ | Code | Value | +------+-------+ | A | 1 | | B | 2 | | D | 4 | +------+-------+ ,结果在此实例中会相同。

我不确定这是否可以接受,但它会返回正确的结果:

select 
    o.Code
  , coalesce(s.Value,x.Value) as Value
from #Objects o
  left join #Settings s 
    on o.Code = s.Code
  inner join #Settings x
    on x.Code = 'Other'

rextester演示:http://rextester.com/EBUG86037

返回:

  var chart = sheet.getCharts()[0];
  var blob = chart.getBlob().setContentType('image/jpeg');
  var bytes = blob.getBytes();
  var base64String = Utilities.base64Encode(bytes);
  var site = SitesApp.getSite('aperturelabs.it', 'testkpi');
  var page = site.getChildByName('home');
  var html = '<img src="data:' + blob.getContentType() + ';base64,' + base64String + '"/>';
  Logger.log(html);
  page.setHtmlContent(html);

@RBarryYoung喜欢的形式:

<img src="javascript:void(0);" alt="img name">

这更简洁(为您节省许多keystrokes)并生成与我的初始答案相同的执行计划。无论是或多或少都清楚它在做什么取决于你,我喜欢这两个。

答案 2 :(得分:1)

如果有一个&#34;其他&#34;然后您可以只执行join两次 - left join和另一次实际为cross join

select o.Code,
    coalesce(s.Value, s2.value) as value
from #Objects o
left join #Settings s on o.Code = s.Code
join #Settings s2 on s2.Code = 'Other'

答案 3 :(得分:1)

另一种方法是使用CTE为[#Object]表添加一个附加列[Alternative_code],该列具有值&#34;其他&#34;对于[#Settings]中不存在的[Code] 然后使用此CTE与#Settings表连接,如下所示

    $(document).on( "click", "#selector", function() {
  console.log( $( this ).text() );
});