在列中的两个值之间重复值

时间:2019-01-14 20:47:22

标签: sql sql-server sql-server-2014 recursive-cte

我正在尝试在列中重复第一个特定的非空值,直到同一列中的下一个特定的非空值。我该怎么办?

数据如下:

ID | Msg  
---+-----
 1 |     
 2 |  
 3 |  
 4 |  
 5 | Beg  
 6 | End  
 7 |  
 8 | Beg  
 9 |  
10 |   
11 |  
12 | End

应该是这样的:

ID | Msg  
---+-----
 1 |     
 2 |  
 3 |  
 4 |  
 5 | Beg  
 6 | End  
 7 |  
 8 | Beg    
 9 | Beg   
10 | Beg    
11 | Beg  
12 | End

我查看了LAG()LEAD(),但我一直认为我必须为此使用CURSOR。我只是知道这些,但还没有在这种情况下使用过。

5 个答案:

答案 0 :(得分:6)

另一个选择是使用标志和sum() over

示例

Select ID
      ,Msg = case when sum( case when [Msg]='Beg' then  1 when [Msg]='End' then -1  else 0 end ) over (order by ID) = 1 and Msg='' then 'Beg' else Msg end
 From  YourTable

返回

ID  Msg
1   
2   
3   
4   
5   Beg
6   End
7   
8   Beg
9   Beg
10  Beg
11  Beg
12  End

答案 1 :(得分:4)

由于您使用的是MSSQL,因此可以编写CTE以获得所需的结果。

尝试此CTE:

declare @tab table
(
    id int,
    msg char(3)
)

insert into @tab
values  
(1, ''),
(2, ''),   
(3, ''),   
(4, ''),   
(5, 'Beg'),   
(6, 'End'),   
(7, ''),   
(8, 'Beg'),   
(9, ''),   
(10, ''),
(11, ''),   
(12, 'End')

;with cte as
(
    select top 1 tab.id, tab.msg
    from @tab tab
    order by tab.id

    union all

    select tab.id, case when tab.msg = '' and cte.msg = 'beg' then cte.msg else tab.msg end
    from @tab tab
    inner join cte cte on cte.id + 1 = tab.id
)

select *
from cte

答案 2 :(得分:3)

数据

import React from "react";
import Head from "next/head";
import Link from "next/link";
import { unsetToken } from "../lib/auth";
import { Container, Nav, NavItem } from "reactstrap";
import defaultPage from "../hocs/defaultPage";
import Cookie from "js-cookie";

class Layout extends React.Component {
  constructor(props) {
    super(props);
  }
  static async getInitialProps({ req }) {
    let pageProps = {};
    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx);
    }

    return { pageProps, isAuthenticated };
  }
  render() {
    const { isAuthenticated, children } = this.props;
    const title = "Welcome to Nextjs";
    return (
      <div>
        <Head>
          <title>{title}</title>
          <meta charSet="utf-8" />
          <meta
            name="viewport"
            content="initial-scale=1.0, width=device-width"
          />
          <link
            rel="stylesheet"
            href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
            integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
            crossOrigin="anonymous"
          />
          <script src="https://js.stripe.com/v3" />
        </Head>
        <header>
          <Nav className="navbar navbar-dark bg-dark">
            <NavItem>
              <Link href="/">
                <a className="navbar-brand">Home</a>
              </Link>
            </NavItem>
            {isAuthenticated ? (
              <>
                <NavItem className="ml-auto">
                  <span style={{ color: "white", marginRight: 30 }}>
                    {this.props.loggedUser}
                  </span>
                </NavItem>
                <NavItem>
                  <Link href="/">
                    <a className="logout" onClick={unsetToken}>
                      Logout
                    </a>
                  </Link>
                </NavItem>
              </>
            ) : (
              <>
                <NavItem className="ml-auto">
                  <Link href="/signin">
                    <a className="nav-link">Sign In</a>
                  </Link>
                </NavItem>

                <NavItem>
                  <Link href="/signup">
                    <a className="nav-link"> Sign Up</a>
                  </Link>
                </NavItem>
              </>
            )}
          </Nav>
        </header>
        <Container>{children}</Container>
        {/* <footer className="footer">
          {"Strapi footer"}
          <style jsx>
            {`
              .footer {
                position: absolute;
                bottom: 0;
                width: 100%;
                height: 60px;
                line-height: 60px;
                background-color: #f5f5f5;
              }
              a:hover {
                cursor: pointer;
                color: yellow;
              }
            `}
          </style>
        </footer> */}
      </div>
    );
  }
}

export default defaultPage(Layout);

查询

DECLARE @id AS TABLE (
    ID INT
,   MSG VARCHAR(3)
)

INSERT INTO @ID (ID, MSG)
SELECT 1, ''
UNION
SELECT 2, ''
UNION
SELECT 3, ''
UNION
SELECT 4, ''
UNION
SELECT 5, 'Beg'
UNION
SELECT 6, 'End'
UNION
SELECT 7, ''
UNION
SELECT 8, 'Beg'
UNION
SELECT 9, ''
UNION
SELECT 10, ''
UNION
SELECT 11, ''
UNION
SELECT 12, 'End'

答案 3 :(得分:3)

这里是没有自我连接的sql-仅使用窗口函数

select
     dat.id, 
     isnull(nullif(max(dat.msg) over (partition by dat.gr), 'End'), dat.msg) as msg
from (
    select
         dat.id,
         dat.msg,
         dat.wind + sum(dat.is_end) over (order by dat.id) as gr
    from (
        select
             t.id, 
             t.msg,
             sum(iif(t.msg = 'Beg' ,1,0)) over (order by t.id) as wind,
             iif (t.msg = 'End', 1, 0) as is_end
        from t
    ) dat
) dat

答案 4 :(得分:1)

您可以尝试使用以下代码,该代码将适用于您询问的情况,但不能确定它是否适用于所有其他情况,因为case语句特定于上述位置:

WITH cte AS(
SELECT *, LEAD(Msg, 1, 0) OVER (ORDER BY ID) AS leadval, LAG(Msg, 1, 0) OVER (ORDER BY ID) AS lagval
FROM msg),
cte2 AS(
SELECT cte.ID,
       cte.Msg,
       cte.leadval,
       cte.lagval,
       CASE WHEN cte.Msg = 'Beg' THEN 'Beg'
       WHEN cte.Msg = '' AND cte.leadval = '' AND cte.lagval = 'Beg' THEN 'Beg'
       WHEN cte.Msg = '' AND cte.leadval = 'END' THEN 'Beg'
       ELSE cte.Msg end AS Msg2
FROM cte), cte3 AS(
SELECT *, LEAD(cte2.Msg2, 1, 0) OVER (ORDER BY cte2.ID) AS 'LeadVal2'
FROM cte2)
SELECT ID, CASE WHEN cte3.Msg2 = '' AND cte3.LeadVal2 = 'Beg' AND cte3.leadval <> 'Beg' THEN 'Beg' ELSE cte3.Msg2 END AS msg
FROM cte3

输出:

enter image description here