【问题标题】:Use only the month in a date for a query仅使用日期中的月份进行查询
【发布时间】:2019-10-18 07:52:22
【问题描述】:

我正在寻找一种在请求中操纵月份的方法,该请求是从日期中获得的。 (这不是 MVVM)

我如何得到日期:

<Calendar x:Name="selectionMois" DisplayMode="Year" SelectionMode="SingleDate" 
    DisplayModeChanged="selectionMois_DisplayModeChanged"
    HorizontalAlignment="Left" Margin="0,55,0,0" VerticalAlignment="Top" 
    AllowDrop="True" Height="185" Width="226">

private void selectionMois_DisplayModeChanged( object sender, CalendarModeChangedEventArgs e )
{
    selectionMois.DisplayMode = CalendarMode.Year;
    this.dtMois = selectionMois.DisplayDate;
    LabelMois_Refresh();

    if( listAgentsCoches != null )
    {
        if( listAgentsCoches.Count > 0 ) BtImprimer.IsEnabled = true;
        else BtImprimer.IsEnabled = false;
    }
    else BtImprimer.IsEnabled = false;
}

this.dtMonth 包含"YYYYY\MM\01" 格式的日期。

现在我有一个查询或想选择在所选月份有合同(合同)的代理。

我想做这样的事情:

StSQL ="SELECT DISTINCT Agent_Etablissement.Matricule, Nom, Prénom FROM Agent_Etablissement, Agents, contrats
        INNER JOIN CONTRATS ON Contrats.Matricule = Agents.Matricule AND  Contrats.IDEtablissement=Agent_Etablissement.IDEtablissement
        WHERE a contract exists for the chosen month

“Contrats”表包含开始日期和结束日期(这个可以为空)。

如何仅选择所选月份中存在的那些合同?

编辑:SQL 服务器数据库

【问题讨论】:

  • 由于日期时间查询可能是特定于数据库的,因此您使用哪个数据库会很有趣。
  • SQL 服务器,对不起!
  • 您想要获得与所选月份的开始或结束日期匹配的任何合同,还是想要获得跨越所选月份的任何合同?在您的示例中,第一行将返回什么?它跨越数年,所以您希望每个月都匹配吗?还是只有 12 月或 6 月?另外,您是否考虑过这一年?
  • 例如,如果我选择 10 月,则所有存在于 10 月的合同:无论是在 12 月结束,还是在 10 月 15 日结束。感谢您的时间。
  • 是否保证日期 fin 将始终包含月份的最后一天,例如2019-02-28 和 2020-02-29?

标签: c# sql sql-server wpf


【解决方案1】:

例如,如果我选择 10 月,则所有存在于 10 月的合同:无论它们是在 12 月结束,还是在 10 月 15 日结束。

翻译成

SELECT * FROM CONTRACTS
WHERE 
      ([DateDebut] >= '20191001' AND [DateDebut] <= EOMONTH('20191001')) -- starting in Oct
   OR ([DateFin] >= '20191001'   AND [DateFin] <= EOMONTH('20191001')) -- ending in Oct
   OR ([DateDebut] < '20191001'  AND ([DateFin] > EOMONTH('20191001') OR [DateFin] IS null)) -- started before Oct, but not ended

示例

create table contracts ( [Id] varchar(3), [DateDebut] Date , [DateFin] Date, [Name] varchar(50) );
insert into contracts (id, [DateDebut], [DateFin], [Name]) values 
('1', '20120618', '20190920','[-] Before Oct'),
('2', '20190915', '20191015','[+] Ends middle of Oct'), 
('3', '20191020', '20191021','[+] Fully in Oct'),
('4', '20191028', '20191224','[+] Ends after Oct'),
('5', '20191128', '20191224','[-] After Oct'),
('6', '20190901', '20191001','[+] Ends 1st of Oct'),
('7', '20191001', '20191201','[+] Starts 1st of Oct'),
('8', '20191001', '20191031','[+] Full month'),
('9', '20191031', '20191201','[+] Starts 31st of Oct'),
('10', '20190901', '20191201','[+] Starts before Oct and ends after Oct');


SELECT * FROM CONTRACTS
WHERE 
--NOT(
      ([DateDebut] >= '20191001' AND [DateDebut] <= EOMONTH('20191001')) -- starting in Oct
   OR ([DateFin] >= '20191001'   AND [DateFin] <= EOMONTH('20191001')) -- ending in Oct
   OR ([DateDebut] < '20191001'  AND ([DateFin] > EOMONTH('20191001') OR [DateFin] IS null)) -- started before Oct, but not ended
--)

返回

Id  DateDebut   DateFin     Name
2   2019-09-15  2019-10-15  [+] Ends middle of Oct
3   2019-10-20  2019-10-21  [+] Fully in Oct
4   2019-10-28  2019-12-24  [+] Ends after Oct
6   2019-09-01  2019-10-01  [+] Ends 1st of Oct
7   2019-10-01  2019-12-01  [+] Starts 1st of Oct
8   2019-10-01  2019-10-31  [+] Full month
9   2019-10-31  2019-12-01  [+] Starts 31st of Oct
10  2019-09-01  2019-12-01  [+] Strats before Oct and ends after Oct

只是为了确保没有(...)返回

Id  DateDebut   DateFin     Name
1   2012-06-18  2019-09-20  [-] Before Oct
5   2019-11-28  2019-12-24  [-] After Oct

Fiddle

注意:我使用 '20191001' 而不是 '2019-10-01' 以避免出现表示 1 月 10 日而不是 10 月 1 日的情况。

【讨论】:

    【解决方案2】:

    您可以使用MONTH() 从日期时间中选择月份值。下面应该起作用,选择所选日期(月份)大于开始日期且小于结束日期(如果它不为空)的任何合同。

    SELECT DISTINCT Agent_Etablissement.Matricule, Nom, Prénom 
    FROM Agent_Etablissement, Agents, contrats
    INNER JOIN CONTRATS ON Contrats.Matricule = Agents.Matricule AND  Contrats.IDEtablissement=Agent_Etablissement.IDEtablissement
    WHERE (MONTH(@myDate) BETWEEN MONTH(StartDate) AND MONTH(EndDate)) 
       OR (MONTH(StartDate) >= MONTH(@myDate) AND EndDate IS NULL )
    

    注意:这不考虑年份,因此将返回跨越 10 月的所有合同(如果选择了 10 月)。


    下面也考虑了年份:

    WHERE (MONTH(@myDate) BETWEEN MONTH(StartDate) AND MONTH(EndDate) 
       OR (MONTH(StartDate) >= MONTH(@myDate) AND EndDate IS NULL)) 
    
      AND (YEAR(@myDate) BETWEEN YEAR(StartDate) AND YEAR(EndDate) 
       OR (YEAR(StartDate) >= YEAR(@myDate) AND EndDate IS NULL))
    

    请注意:当使用较长的日期范围时,此答案并不可靠(例如,如果 [DateDebut][DateFin] 跨越一年的开始/结束,则此查询将失败)。当month(DateDebut) 大于month(DateFin)(即日期跨越一年的开始/结束)时,您可以向查询添加更多条件来处理情况。

    但是,更好的方法是使用&gt;=&lt;= 运算符或BETWEEN 过滤DateDebutDateFin,以过滤日期,如其他答案所示。

    例如:

    WHERE [DateDebut] >= @monthStart
     AND ([DateFin] <= @monthEnd OR [DateFin] IS NULL)
    

    【讨论】:

    • 开始和结束日期跨两年是否有效?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-16
    • 1970-01-01
    • 2014-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多