sql - 将Excel公式转换为SQL查询

标签 sql sql-server excel

这是 Excel 文件,我可以在其中使用公式获取 TAT ORIG:

enter image description here

=IF((X3-W3)*24<=24,(X3-W3)*24,
IF(AND(WEEKDAY(W3,2)<6,WEEKDAY(X3,2)<6),(NETWORKDAYS(W3,X3)-1+MOD(X3,1)-MOD(W3,1))*24,
IF(OR(WEEKDAY(W3,2)>5,WEEKDAY(X3,2)>5),(NETWORKDAYS(W3,X3)*24))))

这是我在 EXCEL 中获取 TAT ORIG 值的公式

我需要转换相同的公式 或技巧在现有 SQL 表中获取相同的值,列名称为 tat_orig

在此表中,我需要使用 SQL 查询来计算 tat_orig:

enter image description here

最佳答案

哇,我没想到会花这么长时间。这是我得到的:

--Network days shim
IF OBJECT_ID(N'NETWORKDAYS', N'FN') IS NOT NULL
    DROP FUNCTION dbo.NETWORKDAYS;
GO
CREATE FUNCTION dbo.NETWORKDAYS(@d1 datetime, @d2 datetime )
RETURNS int
AS
BEGIN
    DECLARE @w1 int = DATEPART(weekday, @d1);
    DECLARE @w2 int = DATEPART(weekday, @d1);
    DECLARE @dd float = FLOOR(DATEDIFF(ms, @d1, @d2) / 86400000.0);

    -- network days is based on a holidays table; I just added this date arbitrarily so that
    -- the results match what Excel says
    DECLARE @holidays TABLE(holiday datetime);
    INSERT INTO @holidays VALUES
        ('2016-06-15');

    RETURN (@dd + @w2 - @w1) / 7 * 5 +
            @w2 - @w1 + 1 +
            IIF(@w2 = 7, -1, 0) +
            IIF(@w1 = 1, -1, 0) +
            (SELECT COUNT(*) FROM @holidays WHERE @d1 <= holiday AND holiday < @d2);
END
GO

-- turn around time shim
IF OBJECT_ID(N'TURNAROUND', N'FN') IS NOT NULL
    DROP FUNCTION dbo.TURNAROUND;
GO
CREATE FUNCTION dbo.TURNAROUND(@d1 datetime, @d2 datetime)
RETURNS float
AS
BEGIN
    DECLARE @w1 int = DATEPART(weekday, @d1);
    DECLARE @w2 int = DATEPART(weekday, @d1);
    DECLARE @nd int = dbo.NETWORKDAYS(@d1, @d2);

    DECLARE @hd float = DATEDIFF(ms, @d1, @d2) / 3600000.0;
    DECLARE @td float = DATEDIFF(ms, CAST(@d1 AS TIME), CAST(@d2 AS TIME)) / 86400000.0;

    RETURN (

    IIF(@hd <= 24.0,
        @hd,
        IIF(@w1 < 6 AND @w2 < 6,
            24 * (@nd - 1 + @td),
            IIF(@w2 > 5 OR @w1 > 5,
                24 * @nd, 0))));
END
GO

-- the data
DECLARE @items TABLE
(
 time_created datetime,
 time_responded datetime
);

INSERT INTO @items VALUES
('2016-06-10 15:42:00.000', '2016-06-15 03:03:00.000'),
('2016-06-15 01:28:00.000', '2016-06-15 03:03:00.000'),
('2016-06-14 07:46:00.000', '2016-06-15 03:03:00.000'),
('2016-07-04 05:35:25.000', '2016-07-04 19:05:48.000'),
('2016-07-04 04:56:09.000', '2016-07-04 18:29:28.000'),
('2016-07-04 09:15:33.000', '2016-07-04 22:08:43.000'),
('2016-07-04 08:44:24.000', '2016-07-04 21:40:57.000'),
('2016-07-04 07:14:51.000', '2016-07-04 21:39:24.000');

-- the results
SELECT  time_created, time_responded, dbo.TURNAROUND(time_created, time_responded) AS [TAT Orig] FROM @items;

困难的部分是计算日期算术。您不必声明函数 - 它们的存在是为了清楚起见并计算中间值,但从技术上讲,您应该能够在 SELECT 语句中使用返回值。

顺便说一句,如果您的计算列从下一行获取值,那么您就不走运了 - 这在 SQL 中并非不可能,但也很接近。

我希望这有帮助!

编辑:

我添加了日期差异大垫片。我添加了一年后的测试数据。

--Big datediff shim
IF OBJECT_ID(N'DATEDIFFBIG', N'FN') IS NOT NULL
    DROP FUNCTION dbo.DATEDIFFBIG;
GO
CREATE FUNCTION DATEDIFFBIG(@d1 datetime, @d2 datetime)
RETURNS bigint
AS
BEGIN
    RETURN CONVERT(bigint, DATEDIFF(day, @d1, @d2)) * 86400000 -
        DATEDIFF(second, DATEADD(day, DATEDIFF(day, 0, @d1), 0), @d1) * 1000 +
        DATEDIFF(second, DATEADD(day, DATEDIFF(day, 0, @d2), 0), @d2) * 1000;
END
GO

--Network days shim
IF OBJECT_ID(N'NETWORKDAYS', N'FN') IS NOT NULL
    DROP FUNCTION dbo.NETWORKDAYS;
GO
CREATE FUNCTION dbo.NETWORKDAYS(@d1 datetime, @d2 datetime)
RETURNS int
AS
BEGIN
    DECLARE @w1 int = DATEPART(weekday, @d1);
    DECLARE @w2 int = DATEPART(weekday, @d1);
    DECLARE @dd float = FLOOR(dbo.DATEDIFFBIG(@d1, @d2) / 86400000.0);

    -- network days is based on a holidays table; I just added this date arbitrarily so that
    -- the results match what Excel says
    DECLARE @holidays TABLE(holiday datetime);
    INSERT INTO @holidays VALUES
        ('2016-06-15');

    RETURN (@dd + @w2 - @w1) / 7 * 5 +
            @w2 - @w1 + 1 +
            IIF(@w2 = 7, -1, 0) +
            IIF(@w1 = 1, -1, 0) +
            (SELECT COUNT(*) FROM @holidays WHERE @d1 <= holiday AND holiday < @d2);
END
GO

-- turn around time shim
IF OBJECT_ID(N'TURNAROUND', N'FN') IS NOT NULL
    DROP FUNCTION dbo.TURNAROUND;
GO
CREATE FUNCTION dbo.TURNAROUND(@d1 datetime, @d2 datetime)
RETURNS float
AS
BEGIN
    DECLARE @w1 int = DATEPART(weekday, @d1);
    DECLARE @w2 int = DATEPART(weekday, @d1);
    DECLARE @nd int = dbo.NETWORKDAYS(@d1, @d2);

    DECLARE @hd float = dbo.DATEDIFFBIG(@d1, @d2) / 3600000.0;
    DECLARE @td float = dbo.DATEDIFFBIG(CAST(@d1 AS TIME), CAST(@d2 AS TIME)) / 86400000.0;

    RETURN (

    IIF(@hd <= 24.0,
        @hd,
        IIF(@w1 < 6 AND @w2 < 6,
            24 * (@nd - 1 + @td),
            IIF(@w2 > 5 OR @w1 > 5,
                24 * @nd, 0))));
END
GO

-- the data
DECLARE @items TABLE
(
 time_created datetime,
 time_responded datetime
);

INSERT INTO @items VALUES
('2016-06-10 15:42:00.000', '2016-06-15 03:03:00.000'),
('2016-06-15 01:28:00.000', '2016-06-15 03:03:00.000'),
('2016-06-14 07:46:00.000', '2016-06-15 03:03:00.000'),
('2016-07-04 05:35:25.000', '2016-07-04 19:05:48.000'),
('2016-07-04 04:56:09.000', '2016-07-04 18:29:28.000'),
('2016-07-04 09:15:33.000', '2016-07-04 22:08:43.000'),
('2016-07-04 08:44:24.000', '2016-07-04 21:40:57.000'),
('2016-07-04 07:14:51.000', '2016-07-04 21:39:24.000'),
('2015-07-04 07:14:51.000', '2016-07-04 21:39:24.000');

-- the results
SELECT  time_created, time_responded, dbo.TURNAROUND(time_created, time_responded) AS [TAT Orig] FROM @items;

关于sql - 将Excel公式转换为SQL查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38376386/

相关文章:

sql - 简单的 mysql 查询(我认为) - 选择多行到 1 个字段

mysql - 优化 SQL JOIN 查询

mysql - 使用 SQL 查询和 Nagios 检查 WordPress 上的评论

sql-server - 如何让 ASP.NET MVC 3.0 站点使用默认 SQLEXPRESS 以外的数据库

vba - 我可以使用 VBA 函数将可接受值的(动态)列表返回到 Excel 的数据验证中吗?

javascript - HTTP 状态 500 – 内部服务器错误,同时使用 esign genie api 在 vm 中下载 excel 文件

sql - excel vba - 在电子表格上查询

MySQL 假设我不想要基于所使用的运算符的任何结果

sql-server - 在 Lift 上下文中使用 ScalaQuery 的好例子?

sql - 递归连接