V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
imyasON
V2EX  ›  程序员

一个 SQL 不会写,大佬帮帮忙

  •  
  •   imyasON · 83 天前 · 3058 次点击
    这是一个创建于 83 天前的主题,其中的信息可能已经有所发展或是发生改变。

    假如查询 SELECT COUNT(1) FROM attendance_workday WHERE date_ymd LIKE '202401%'; 大于 0 库中有值 就执行 update 语句,否则 insert 插入语句,这样写会 like 12 次 '202401%', '202402%' ... '202412%'; 一共 12 个月.

    updata 和 insert 语句 每个月份的都不一样,用 sql 脚本我该怎么写,用不了代码。

    一月的 插入: INSERT INTO attendance_workday (date_ymd, is_work) VALUES ('20240101', '1'), ('20240102', '1'), ('20240103', '1'), ('20240104', '1'), ('20240105', '1'), ('20240106', '0'), ('20240107', '0'), ('20240108', '1'), ('20240109', '1'), ('20240110', '1'), ('20240111', '1'), ('20240112', '1'), ('20240113', '1'), ('20240114', '0'), ('20240115', '1'), ('20240116', '1'), ('20240117', '1'), ('20240118', '1'), ('20240119', '1'), ('20240120', '0'), ('20240121', '0'), ('20240122', '1'), ('20240123', '1'), ('20240124', '1'), ('20240125', '1'), ('20240126', '1'), ('20240127', '0'), ('20240128', '0'), ('20240129', '1'), ('20240130', '1'), ('20240131', '1');

    更新: UPDATE attendance_workday SET date_ymd = '20240101', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240102', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240103', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240104', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240105', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240106', is_work = '0'; UPDATE attendance_workday SET date_ymd = '20240107', is_work = '0'; UPDATE attendance_workday SET date_ymd = '20240108', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240109', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240110', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240111', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240112', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240113', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240114', is_work = '0'; UPDATE attendance_workday SET date_ymd = '20240115', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240116', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240117', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240118', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240119', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240120', is_work = '0'; UPDATE attendance_workday SET date_ymd = '20240121', is_work = '0'; UPDATE attendance_workday SET date_ymd = '20240122', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240123', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240124', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240125', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240126', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240127', is_work = '0'; UPDATE attendance_workday SET date_ymd = '20240128', is_work = '0'; UPDATE attendance_workday SET date_ymd = '20240129', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240130', is_work = '1'; UPDATE attendance_workday SET date_ymd = '20240131', is_work = '1';

    19 条回复    2024-02-04 15:31:46 +08:00
    hay313955795
        1
    hay313955795  
       83 天前
    这要写存储过程呗。
    为什么不用业务代码实现
    aahao
        2
    aahao  
       83 天前
    iyiluo
        3
    iyiluo  
       83 天前
    gpt 啊,这种活干嘛不问 gpt
    lsk569937453
        4
    lsk569937453  
       83 天前
    直接写代码实现。用 sql 实现的话后期维护够你喝一壶的
    vhjxbc
        5
    vhjxbc  
       83 天前
    好的,我理解你的需求了。你想检查 attendance_workday 表中是否有某个特定月份(比如,2024 年 1 月)的记录。如果有记录,你想执行一个 UPDATE 语句;否则,你想执行一个 INSERT 语句。

    下面是一个可以满足你需求的脚本:

    sql
    Copy code
    DECLARE @MonthToCheck VARCHAR(6) = '202401'; -- 将此值更改为所需的月份

    IF EXISTS (SELECT 1 FROM attendance_workday WHERE date_ymd LIKE @MonthToCheck + '%')
    BEGIN
    -- 更新语句
    UPDATE attendance_workday
    SET is_work = CASE
    WHEN date_ymd = @MonthToCheck + '01' THEN '1'
    WHEN date_ymd = @MonthToCheck + '02' THEN '1'
    -- 依此类推,覆盖月份中的所有天
    WHEN date_ymd = @MonthToCheck + '31' THEN '1'
    END
    WHERE date_ymd LIKE @MonthToCheck + '%';
    END
    ELSE
    BEGIN
    -- 插入语句
    INSERT INTO attendance_workday (date_ymd, is_work)
    VALUES
    (@MonthToCheck + '01', '1'),
    (@MonthToCheck + '02', '1'),
    -- 依此类推,覆盖月份中的所有天
    (@MonthToCheck + '31', '1');
    END
    在运行脚本之前,用实际的月份替换 @MonthToCheck 。这个脚本使用了条件性的 EXISTS 检查来判断表中是否存在指定月份的记录。如果存在记录,就执行 UPDATE 语句;否则,执行 INSERT 语句。脚本中包含了月份中每一天的占位符,你需要根据实际情况调整。
    dog82
        6
    dog82  
       83 天前
    不是有 ON DUPLICATE KEY 和 merge 语法么,看能不能用上
    rxmt
        7
    rxmt  
       83 天前
    GPT 侠帮你问了。。

    要在 SQL 脚本中实现您描述的功能,可以使用一个控制流程结构来先检查每个月份是否存在数据,然后根据检查结果执行相应的 INSERT 或 UPDATE 操作。但请注意,SQL 本身并不直接支持循环或条件分支,这通常是通过存储过程或脚本语言来实现的。下面是一个简化的示例,说明如何为一个月份实现这个过程。

    sql
    Copy code
    -- 检查 2024 年 1 月的数据是否存在
    DECLARE @count INT;
    SELECT @count = COUNT(1) FROM attendance_workday WHERE date_ymd LIKE '202401%';

    -- 根据结果执行相应操作
    IF @count > 0
    BEGIN
    -- 数据存在时,执行更新操作
    UPDATE attendance_workday SET is_work = '1' WHERE date_ymd = '20240101';
    -- ... 后续更新操作
    END
    ELSE
    BEGIN
    -- 数据不存在时,执行插入操作
    INSERT INTO attendance_workday (date_ymd, is_work)
    VALUES
    ('20240101', '1'),
    -- ... 后续插入操作
    ('20240131', '1');
    END
    这个示例是在假设您使用的是支持 T-SQL (例如 SQL Server )的数据库系统。如果您使用的是其他类型的数据库系统(如 MySQL 、PostgreSQL 等),可能需要使用不同的语法。

    此外,对于您描述的 12 个月份,您需要为每个月份重复这个过程。这可能导致代码量较大。为了简化这一过程,您可能需要考虑使用数据库的编程功能(如存储过程)或者将逻辑移动到应用程序代码中,这样可以更容易地实现循环和条件逻辑。

    在实现此类操作时,请确保考虑事务的使用,以保持数据的一致性和完整性。如果您不熟悉高级 SQL 技巧或存储过程的编写,建议咨询熟悉数据库编程的专业人士。
    corcre
        8
    corcre  
       83 天前   ❤️ 1
    这不工作日历吗...
    你有数据的话全都查到临时表里面开个游标然后在实体表里面 if exists update ..... else insert....不就好了, 一年的数据量才 365 天吧
    lll5758
        9
    lll5758  
       83 天前
    啊?那还要后端干什么呢,直接连接数据库得了
    yjxjn
        10
    yjxjn  
       83 天前   ❤️ 1
    如果你想在数据库中进行检查,然后根据条件执行不同的 SQL 语句,可以使用存储过程( Stored Procedure )或者函数。下面是一个简单的例子,假设你使用的是 MySQL 数据库:

    -- 创建存储过程
    DELIMITER //

    CREATE PROCEDURE UpdateOrInsertForMonth(IN target_month VARCHAR(6))
    BEGIN
    DECLARE record_count INT;

    -- 检查记录数量
    SELECT COUNT(1) INTO record_count FROM attendance_workday WHERE date_ymd LIKE CONCAT(target_month, '%');

    -- 根据记录数量执行不同的 SQL 语句
    IF record_count > 0 THEN
    -- 如果有记录,则执行 UPDATE 语句
    UPDATE your_table SET your_column = 'new_value' WHERE date_ymd LIKE CONCAT(target_month, '%');
    ELSE
    -- 如果没有记录,则执行 INSERT 语句
    INSERT INTO your_table (date_ymd, your_column) VALUES ('20240101', 'new_value');
    -- 这里请根据实际表结构和字段进行修改
    END IF;
    END //

    DELIMITER ;

    上述例子中,your_table 和 your_column 需要替换为你实际的表名和列名。存储过程中的逻辑可以根据你的需求进行修改。

    然后,你可以调用这个存储过程,传入不同的月份作为参数,例如:

    -- 调用存储过程,传入月份 '202401'
    CALL UpdateOrInsertForMonth('202401');
    liprais
        11
    liprais  
       83 天前   ❤️ 4
    楼上这些深刻揭示了如果你不会写 code,那大模型生成的 code 对你也没什么用
    RockShake
        12
    RockShake  
       83 天前   ❤️ 1
    你应该有数据库的读写权限,怎么会用不了代码呢,VBA 也是代码,这个逻辑放到代码层面实现会简单很多
    xuanbg
        13
    xuanbg  
       83 天前
    代码写个循环,给 sql 传参数“'2024xx”就行
    imyasON
        14
    imyasON  
    OP
       83 天前
    谢谢各位,不写代码是因为我没有数据库连接权限,只能把脚本写好交给别人执行,按照上面的写了一个存储过程,我本地测下
    shen13176101
        15
    shen13176101  
       83 天前
    路看窄了,不应该把这个看作是 sql ,应该看作是需求。以需求的角度来写 sql ,
    ZField
        16
    ZField  
       83 天前
    = = 如果数据量较少并且单次使用,不如直接大量的单条语句,既简单又可以控制风险
    gkinxin
        17
    gkinxin  
       83 天前
    @Livid #5 vhjxbc #7 rxmt #10 yjxjn GPT 回答
    isnullstring
        18
    isnullstring  
       83 天前   ❤️ 1
    限制一定要 SQL 的话,两种方式
    1 、存储过程,游标循环传日期进去处理,调用是一个存储过程,处理是一个存储过程
    2 、动态 SQL ,也是游标循环传日期,一个存储过程
    3 、按 date_ymd 的前 6 位汇总,创建临时表记录对应日期库存是否大于 0 ,然后分别写 Insert 和 update ,条件就是临时表了
    我会选第三种,不需要用游标,不需要分存储过程,不需要动态 SQL ,不需要 Ctrl+CV ,不需要管日期,即使你的 attendance_workday 用了 100 年 ,表中数据才 100*365=36500 ,当然我相信里面还有其他细节没考虑,自行完善
    hackerfans
        19
    hackerfans  
       83 天前
    BEGIN
    DECLARE month_num INT;

    SET month_num = 1; -- Start with January

    WHILE month_num <= 12 DO
    DECLARE month_str CHAR(2);
    SET month_str = LPAD(month_num, 2, '0'); -- Format month as 01, 02, ...

    DECLARE count_rows INT;
    SET count_rows = (SELECT COUNT(1) FROM attendance_workday WHERE date_ymd LIKE CONCAT('2024', month_str, '%'));

    IF count_rows > 0 THEN
    -- Perform UPDATE statements for the current month
    -- Replace placeholders with actual UPDATE statements for each month
    EXECUTE IMMEDIATE CONCAT('UPDATE attendance_workday SET date_ymd = '2024', month_str, '01', ', is_work = '1' WHERE date_ymd LIKE '2024', month_str, '%'');
    -- Add similar UPDATE statements for other dates in the month
    ELSE
    -- Perform INSERT statements for the current month
    -- Replace placeholders with actual INSERT statements for each month
    EXECUTE IMMEDIATE CONCAT('INSERT INTO attendance_workday (date_ymd, is_work) VALUES (''2024', month_str, '01'', ''1''), (''2024', month_str, '02'', ''1''), ...');
    -- Add remaining date-is_work pairs for the month
    END IF;

    SET month_num = month_num + 1; -- Move to the next month
    END WHILE;
    END
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2959 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 08:05 · PVG 16:05 · LAX 01:05 · JFK 04:05
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.