【问题标题】:SQL query_select different column based on conditionSQL查询根据条件选择不同的列
【发布时间】:2022-09-27 23:16:45
【问题描述】:

这是我的两张桌子:

  • Table1 有开始日期和结束日期。
  • Table2 具有 AllMonths 和 Month 和 Value 列。

创建这些表的脚本。

CREATE TABLE [dbo].[Table1](
    [EmployeeId] [int] NULL,
    [CompanyId] [int] NULL,
    [StartDate] [datetime] NULL,
    [EndDate] [datetime] NULL
) ON [PRIMARY]

INSERT INTO [dbo].[Table1] VALUES(12345,1205,\'2021-01-01 00:00:00.000\',\'2021-06-30 00:00:00.000\')
INSERT INTO [dbo].[Table1] VALUES(23211,1205,\'2021-01-01 00:00:00.000\',\'2021-05-31 00:00:00.000\')
INSERT INTO [dbo].[Table1] VALUES(23211,1205,\'2021-07-01 00:00:00.000\',\'2021-09-30 00:00:00.000\')
INSERT INTO [dbo].[Table1] VALUES(23141,1205,\'2021-01-01 00:00:00.000\',\'2021-11-30 00:00:00.000\')
INSERT INTO [dbo].[Table1] values(54333,1205,\'2021-01-01 00:00:00.000\',\'2021-05-31 00:00:00.000\') 
INSERT INTO [dbo].[Table1] values(76553,1205,\'2021-01-01 00:00:00.000\',\'2021-12-31 00:00:00.000\')
INSERT INTO [dbo].[Table1] values(55555,1205,\'2021-08-01 00:00:00.000\',\'2021-09-30 00:00:00.000\')
INSERT INTO [dbo].[Table1] values(55555,1205,\'2021-11-01 00:00:00.000\',\'2021-11-30 00:00:00.000\')


CREATE TABLE [dbo].[Table2](
    [EmployeeId] [int] NULL,
    [CompanyId] [int] NULL,
    [AllMonths] [int] NULL,
    [Month] [int] NULL,
    [Value] [int] NULL
)

INSERT INTO [dbo].[Table2] VALUES(23211,1205,NULL,1,1)
INSERT INTO [dbo].[Table2] VALUES(23211,1205,NULL,2,1)
INSERT INTO [dbo].[Table2] VALUES(23211,1205,NULL,3,1)
INSERT INTO [dbo].[Table2] VALUES(23211,1205,NULL,4,2)
INSERT INTO [dbo].[Table2] VALUES(23211,1205,NULL,5,2)
INSERT INTO [dbo].[Table2] VALUES(23211,1205,NULL,6,2)
INSERT INTO [dbo].[Table2] VALUES(23211,1205,NULL,7,2)
INSERT INTO [dbo].[Table2] VALUES(23211,1205,NULL,8,2)
INSERT INTO [dbo].[Table2] VALUES(23211,1205,NULL,9,2)
INSERT INTO [dbo].[Table2] VALUES(23211,1205,NULL,11,2)
INSERT INTO [dbo].[Table2] VALUES(23211,1205,NULL,12,2)
INSERT INTO [dbo].[Table2] VALUES(23141,1205,1,NULL,NULL)
INSERT INTO [dbo].[Table2] VALUES(23141,1205,1,NULL,NULL)
INSERT INTO [dbo].[Table2] VALUES(23141,1205,1,NULL,NULL)
INSERT INTO [dbo].[Table2] VALUES(23141,1205,1,NULL,NULL)
INSERT INTO [dbo].[Table2] VALUES(23141,1205,1,NULL,NULL)
INSERT INTO [dbo].[Table2] VALUES(23141,1205,1,NULL,NULL)
INSERT INTO [dbo].[Table2] VALUES(23141,1205,1,NULL,NULL)
INSERT INTO [dbo].[Table2] VALUES(23141,1205,1,NULL,NULL)
INSERT INTO [dbo].[Table2] VALUES(23141,1205,1,NULL,NULL)
INSERT INTO [dbo].[Table2] VALUES(23141,1205,1,NULL,NULL)
INSERT INTO [dbo].[Table2] VALUES(23141,1205,1,NULL,NULL)
INSERT INTO [dbo].[Table2] VALUES(23141,1205,1,NULL,NULL)
INSERT INTO [dbo].[Table2] VALUES(12345,1205,NULL,1,1)
INSERT INTO [dbo].[Table2] VALUES(12345,1205,NULL,2,1)
INSERT INTO [dbo].[Table2] VALUES(12345,1205,NULL,3,1)
INSERT INTO [dbo].[Table2] VALUES(12345,1205,NULL,4,1)
INSERT INTO [dbo].[Table2] VALUES(12345,1205,NULL,5,1)
INSERT INTO [dbo].[Table2] VALUES(12345,1205,NULL,6,1)
INSERT INTO [dbo].[Table2] VALUES(12345,1205,NULL,7,1)
INSERT INTO [dbo].[Table2] VALUES(12345,1205,NULL,8,2)
INSERT INTO [dbo].[Table2] VALUES(12345,1205,NULL,9,2)
INSERT INTO [dbo].[Table2] VALUES(12345,1205,NULL,11,2)
INSERT INTO [dbo].[Table2] VALUES(12345,1205,NULL,12,2)
INSERT INTO [dbo].[Table2] VALUES(54333,1205,NULL,1,1) 
INSERT INTO [dbo].[Table2] VALUES(54333,1205,NULL,2,2)
INSERT INTO [dbo].[Table2] VALUES(54333,1205,NULL,3,2)
INSERT INTO [dbo].[Table2] VALUES(54333,1205,NULL,4,2) 
INSERT INTO [dbo].[Table2] VALUES(54333,1205,NULL,5,2)
INSERT INTO [dbo].[Table2] VALUES(54333,1205,NULL,6,2)
INSERT INTO [dbo].[Table2] VALUES(54333,1205,NULL,7,2)
INSERT INTO [dbo].[Table2] VALUES(54333,1205,NULL,8,1)
INSERT INTO [dbo].[Table2] VALUES(54333,1205,NULL,9,1)
INSERT INTO [dbo].[Table2] VALUES(54333,1205,NULL,10,1)
INSERT INTO [dbo].[Table2] VALUES(54333,1205,NULL,11,1)
INSERT INTO [dbo].[Table2] VALUES(54333,1205,NULL,12,1)
INSERT INTO [dbo].[Table2] VALUES(76553,1205,NULL,1,1)
INSERT INTO [dbo].[Table2] VALUES(76553,1205,NULL,2,2)
INSERT INTO [dbo].[Table2] VALUES(76553,1205,NULL,3,2) 
INSERT INTO [dbo].[Table2] VALUES(76553,1205,NULL,4,2)
INSERT INTO [dbo].[Table2] VALUES(76553,1205,NULL,5,2)
INSERT INTO [dbo].[Table2] VALUES(76553,1205,NULL,6,2) 
INSERT INTO [dbo].[Table2] VALUES(76553,1205,NULL,7,2)
INSERT INTO [dbo].[Table2] VALUES(76553,1205,NULL,8,2)
INSERT INTO [dbo].[Table2] VALUES(76553,1205,NULL,9,2) 
INSERT INTO [dbo].[Table2] VALUES(76553,1205,NULL,10,2)
INSERT INTO [dbo].[Table2] VALUES(76553,1205,NULL,11,NULL)
INSERT INTO [dbo].[Table2] VALUES(76553,1205,NULL,12,NULL)

我想要的输出是:

  • 案例 #1:EmployeeId = 12345

    AllMonths 列为 NULL。 Startdate Jan 和 EndDate Jun。从 jan-jun 开始的所有这些月份在表 2 中具有相同的值。所以 \'EmployeeClass\' 的值为 1。

  • 案例 #2:员工 ID = 23211

    AllMonths 列为 NULL。 Startdate Jan 和 EndDate May 和 Startdate July 和 EndDate Sep. Jan-Mar 的值为 1,而 Apr-May 在表 2 中的值为 2。因此在输出中应将其拆分为两行,Jan-Mar 的“EmployeeClass”值为 1,Apr-May 的值为 2。July-Sep 的值为 2,因此 July-Sep 的值为 2。

  • 案例 #3:EmployeeId = 23141

    AllMonths 列不为空。因此,AllMonths 列中的 \'Final\' 值为 1。

  • 案例 #4:员工 ID = 54333

    AllMonths 列为 NULL。 Startdate Jan 和 EndDate May。在表 2 中,jan 的值为 1,feb-may 的值为 2。因此在输出中应将其分成两行,Jan-Jan 的 \'EmployeeClass\' 值为 1,Feb-May 的值为 2 .

  • 案例 #5:员工 ID = 55555

    表 1 中该员工的两行。但表 2 中没有行。因此,这些行在输出中将可用,且具有 \'EmployeeClass\' 值 \'NULL\'。

  • 案例 #6:员工 ID = 76553

    AllMonths 列为 NULL。 Startdate Jan 和 EndDate Dec. jan 的值为 1,feb-oct 的值为 2,nov-dec 的值为 3,在表 2 中。所以在输出中它应该被分成三行, Jan-Jan \'EmployeeClass\' 的值为 1,Feb-Oct 的值为 2,Nov-Dec 的值为 \'NULL\'。

需要一些帮助来实现这一目标。

  • 请创建包含示例数据的表格,其任务是从 excel 屏幕截图中重新创建它们。您可以使用Markdown Table Generator 之类的工具快速粘贴数据,并在编辑问题时创建一个降价表粘贴到此处。
  • 我用添加的表格脚本编辑了问题
  • SQL服务器版本?另外,你有数字表或日历表吗?
  • Azure SQL Server ...因此寻找没有任何系统编号表的解决方案。
  • 检查我的脚本。我在发布我的脚本后阅读了您的评论

标签: sql sql-server tsql


【解决方案1】:

这将从您提供的示例数据中返回您想要的输出:

SELECT 
    t1.CompanyId
    ,t1.EmployeeId
    ,StartDate  = FORMAT(ISNULL(DATEFROMPARTS(YEAR(StartDate), min(t2.month), 1), StartDate), 'MM/dd/yyyy')
    ,EndDate    = FORMAT(
                    ISNULL(
                        DATEFROMPARTS(YEAR(enddate), max(t2.month), 1)
                        ,DATEADD(dd, -DATEPART(dd, enddate) + 1, enddate)
                    )
                    , 'MM/dd/yyyy')
    ,ISNULL(Allmonths, value) as Final
FROM [Table1] t1
INNER JOIN [Table2] t2 on t1.employeeid = t2.employeeid
                    AND t1.CompanyId = t2.CompanyId
                    AND (   (t2.allmonths IS NOT NULL) 
                            OR (t2.month BETWEEN DATEPART(MM, startdate) AND DATEPART(MM, enddate))
                        )
GROUP BY 
    t1.CompanyId
    ,t1.EmployeeId
    ,StartDate
    ,EndDate
    ,ISNULL(Allmonths, value)
ORDER BY 
    1, 3, 4

【讨论】:

  • 是的......在大多数情况下它工作得很好......如果我编辑员工 54333 的条目,所以结束日期是 2021 年 12 月 31 日,它会失败............插入 [dbo] .[Table1] 值(54333,1205,'2021-01-01 00:00:00.000','2021-12-31 00:00:00.000')。预期输出是 jan-jan 值 is1,feb-jul 为 2,aug-dec 为 1 .....(三行)....但我得到两行 jan-dec 为 1,feb-jul 为 2。 ...你能帮我解决这个问题吗
【解决方案2】:

有2个逻辑,

i) 当 allmonths 为空时 ii) allmonths 不为空

首先以您想要的任何方式创建数字表,

Create Table tblNumber(Number int primary key)

INSERT INTO tblNumber
SELECT TOP 100000 ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS [N]
FROM dbo.syscolumns tb1,dbo.syscolumns tb2

最终脚本,

   select *
,ROW_NUMBER()over( partition by employeeid order by companyid)rn1
into #table1
from table1

;with CTE as
(
select T1.*
,ROW_NUMBER()over(partition by rn1,employeeid order by companyid)rn
,ROW_NUMBER()over(partition by employeeid order by companyid)rn2
,DATEDIFF(month,startdate,enddate)+1monthDiff from #table1 T1
inner join [dbo].[tblNumber1] n on n.number<=(DATEDIFF(month,startdate,enddate)+1)
)
,CTE2 as
(
select T1.*
,dateadd(month,(rn-1),t1.startdate)NewEndDate
from CTE T1

)
,CTE1 as
(
select t1.companyid,t1.employeeid,t1.startdate,dateadd(month,(rn-1),t1.startdate)NewEndDate
,t1.Enddate,rn,rn1
,t2.[value] as Final 
from CTE2 t1
cross apply(select top 1 [value] from table2 t2 where t2.employeeid=t1.employeeid 
and t2.companyid=t1.companyid and month=month(NewEndDate) and allmonths is null)t2
union all
select t1.companyid,t1.employeeid,t1.startdate,dateadd(month,(rn-1),t1.startdate)NewEndDate
,t1.Enddate,rn,rn1
,t2.[allmonths] as Final 
from CTE2 t1
cross apply(select top 1 allmonths from table2 t2 where t2.employeeid=t1.employeeid 
and t2.companyid=t1.companyid  and allmonths is not null)t2

)


select * from
(
select companyid, employeeid,min(NewEndDate)StartDate,eomonth(max(NewEndDate)) EndDate,Final
from CTE1
group by companyid, employeeid,Final,rn1
union all

select t1.companyid,t1.employeeid,t1.startdate,EndDate
,null as Final 
from #table1 t1
where not exists(select 1 from table2 t2 where t2.employeeid=t1.employeeid 
and t2.companyid=t1.companyid  )

)t4
order by employeeid,StartDate

drop table #table1

注意事项

i)我几个小时前采集了样本数据。

ii) 使用其他样本数据进行测试,如果它不适用于其他样本数据,则单独粘贴该样本数据。

iii)两个表都涉及多少行?

iv) 首先让输出得到纠正,然后可以优化查询。

v) 使用各种样本数据进行“allmonths 为空”时的第一次测试

vi) 然后用各种样本数据测试“allmonths is not null”

【讨论】:

  • 插入表 1 值(54333,1205,2021,'2021-01-01 00:00:00.000','2021-05-31 00:00:00.000')插入表 1 值(76553,1205,2021,'2021 -01-01 00:00:00.000','2021-12-31 00:00:00.000')
  • 插入 [dbo].[Table2] 值(54333,1205,NULL,1,1)插入 [dbo].[Table2] 值(54333,1205,NULL,2,2)插入 [dbo].[Table2 ] VALUES(54333,1205,NULL,3,2)INSERT INTO [dbo].[Table2] VALUES(54333,1205,NULL,4,2) INSERT INTO [dbo].[Table2] VALUES(54333,1205,NULL ,5,2)INSERT INTO [dbo].[Table2] VALUES(54333,1205,NULL,6,2)INSERT INTO [dbo].[Table2] VALUES(54333,1205,NULL,7,2)INSERT INTO [ dbo].[Table2] VALUES(54333,1205,NULL,8,1)INSERT INTO [dbo].[Table2] VALUES(54333,1205,NULL,9,1)INSERT INTO [dbo].[Table2] VALUES( 54333,1205,NULL,11,1)INSERT INTO [dbo].[Table2] VALUES(54333,1205,NULL,12,1)
  • 插入 [dbo].[Table2] 值(76553,1205,NULL,1,1)插入 [dbo].[Table2] 值(76553,1205,NULL,2,2)插入 [dbo].[Table2 ] VALUES(76553,1205,NULL,3,2) INSERT INTO [dbo].[Table2] VALUES(76553,1205,NULL,4,2)INSERT INTO [dbo].[Table2] VALUES(76553,1205,NULL ,5,2)INSERT INTO [dbo].[Table2] VALUES(76553,1205,NULL,6,2) INSERT INTO [dbo].[Table2] VALUES(76553,1205,NULL,7,2)INSERT INTO [ dbo].[Table2] VALUES(76553,1205,NULL,8,2)INSERT INTO [dbo].[Table2] VALUES(76553,1205,NULL,9,2) INSERT INTO [dbo].[Table2] VALUES( 76553,1205,NULL,10,2)
  • INSERT INTO [dbo].[Table2] VALUES(76553,1205,NULL,11,NULL)INSERT INTO [dbo].[Table2] VALUES(76553,1205,NULL,12,NULL)
  • 上面输入的 EmployeeId-54333 失败。
猜你喜欢
  • 2014-02-21
  • 1970-01-01
  • 2016-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多