web-dev-qa-db-ja.com

日付パラメータまたはエントリの行がない場合は、日付パラメータの前の最後の日付の行をテーブルから取得しますnull

通貨の為替レートを保持するテーブルがあります。為替レートの取得日を保持するDate列もあります。

一部の日付には行がありますが、為替レートはなく、一部の日付にはそのテーブルに行がありません。

特定の日付の為替レートを取得するには、その日付をパラメーターとして渡す必要があります。

SELECT
    documentHead.r_art AS documentHeadDocClass,
    foreignCurrency.usd_brief AS foreignCurrencyUSDAsk,
    foreignCurrency.usd_geld AS foreignCurrencyUSDBid,
    foreignCurrency.chf_brief AS foreignCurrencyCHFAsk,
    foreignCurrency.chf_geld AS foreignCurrencyCHFBid,
    foreignCurrency.gbp_brief AS foreignCurrencyGBPAsk,
    foreignCurrency.gbp_geld AS foreignCurrencyGBPBid,
    foreignCurrency.jpy_brief AS foreignCurrencyJPYAsk,
    foreignCurrency.jpy_geld AS foreignCurrencyJPYBid,
    documentListPeriods.id AS documentPeriodsID,
    documentListPeriods.von AS documentPeriodsFrom,
    documentListPeriods.bis AS documentPeriodsTo,
    documentListPeriods.tage AS documentPeriodsDays,
    documentListPeriods.rate AS documentPeriodsRate,
    documentListPeriods.wert AS documentPeriodsWorth
    FROM (
        SELECT  documentPeriods.id AS documentPeriodsID,
            documentPeriods.von AS documentPeriodsFrom,
            documentPeriods.bis AS documentPeriodsTo,
            documentPeriods.tage AS documentPeriodsDays,
            documentPeriods.rate AS documentPeriodsRate,
            documentPeriods.wert AS documentPeriodsWorth
        FROM comperiode AS documentPeriods
        WHERE documentPeriods.id = 1
) AS documentListPeriods
INNER JOIN tckopf AS documentHead ON documentHead.id = 1
LEFT OUTER JOIN devisen AS foreignCurrency ON foreignCurrency.datum = documentHead.datum

為替レートが存在し、日付が渡された日付パラメーターまたは渡された日付パラメーターの前の最後の日付と等しい場合、為替レートテーブルの行を取得するにはどうすればよいですか?

問題は:

LEFT OUTER JOIN devisen AS foreignCurrency ON foreignCurrency.datum = documentHead.datum

foreignCurrency.datumの行が存在しない場合、または為替レートがNULLの場合。使用する場合

LEFT OUTER JOIN devisen AS foreignCurrency ON foreignCurrency.datum <= documentHead.datum

すべてforeignCurrency.datum未満になりますが、必要なのは最新の行だけです。

次の例では、日付の行が欠落しているか、すべての列がNULLである行があります。

currencies exchange rates with missing values for a date

documentHead.datum2009-08-09であり、その日付の行がない場合は、前に最新の行が必要です。その場合、2009-08-07の行。

TOP 1を使用して、LEFT OUTER JOINを次のように書き直してみました。

SELECT  documentHead.r_art AS documentHeadDocClass,
    foreignCurrency.usd_brief AS foreignCurrencyUSDAsk,
    foreignCurrency.usd_geld AS foreignCurrencyUSDBid,
    foreignCurrency.chf_brief AS foreignCurrencyCHFAsk,
    foreignCurrency.chf_geld AS foreignCurrencyCHFBid,
    foreignCurrency.gbp_brief AS foreignCurrencyGBPAsk,
    foreignCurrency.gbp_geld AS foreignCurrencyGBPBid,
    foreignCurrency.jpy_brief AS foreignCurrencyJPYAsk,
    foreignCurrency.jpy_geld AS foreignCurrencyJPYBid,
    documentListPeriods.id AS documentPeriodsID,
    documentListPeriods.von AS documentPeriodsFrom,
    documentListPeriods.bis AS documentPeriodsTo,
    documentListPeriods.tage AS documentPeriodsDays,
    documentListPeriods.rate AS documentPeriodsRate,
    documentListPeriods.wert AS documentPeriodsWorth
    FROM (
        SELECT  documentPeriods.id AS documentPeriodsID,
            documentPeriods.von AS documentPeriodsFrom,
            documentPeriods.bis AS documentPeriodsTo,
            documentPeriods.tage AS documentPeriodsDays,
            documentPeriods.rate AS documentPeriodsRate,
            documentPeriods.wert AS documentPeriodsWorth
        FROM comperiode AS documentPeriods
        WHERE documentPeriods.id = $P{document_id}
) AS documentListPeriods
INNER JOIN tckopf AS documentHead ON documentHead.id = $P{document_id}
LEFT OUTER JOIN (
    SELECT TOP 1
        foreignCurrency.usd_brief AS foreignCurrencyUSDAsk,
        foreignCurrency.usd_geld AS foreignCurrencyUSDBid,
        foreignCurrency.chf_brief AS foreignCurrencyCHFAsk,
        foreignCurrency.chf_geld AS foreignCurrencyCHFBid,
        foreignCurrency.gbp_brief AS foreignCurrencyGBPAsk,
        foreignCurrency.gbp_geld AS foreignCurrencyGBPBid,
        foreignCurrency.jpy_brief AS foreignCurrencyJPYAsk,
        foreignCurrency.jpy_geld AS foreignCurrencyJPYBid
    FROM
        devisen AS foreignCurrency
    WHERE
        foreignCurrency.datum <= documentHead.$P!{exchangeRateTiming}
        AND foreignCurrency.datum IS NOT NULL
        AND foreignCurrency.usd_brief IS NOT NULL
        AND foreignCurrency.usd_geld IS NOT NULL
        AND foreignCurrency.chf_brief IS NOT NULL
        AND foreignCurrency.chf_geld IS NOT NULL
        AND foreignCurrency.gbp_brief IS NOT NULL
        AND foreignCurrency.gbp_geld IS NOT NULL
        AND foreignCurrency.jpy_brief IS NOT NULL
        AND foreignCurrency.jpy_geld IS NOT NULL
    ORDER BY foreignCurrency.datum DESC  ) AS foreignCurrency

しかし、iReportでnullポインタ例外が発生します。

Error filling print... Error executing SQL statement for : boss_charterfaktura_document_list_interval_positions 
Setting up the file resolver...  net.sf.jasperreports.engine.JRException: Error executing SQL statement for : boss_charterfaktura_document_list_interval_positions      at net.sf.jasperreports.engine.query.JRJdbcQueryExecuter.createDatasource(JRJdbcQueryExecuter.Java:246)      at net.sf.jasperreports.engine.fill.JRFillDataset.createQueryDatasource(JRFillDataset.Java:1086)      at net.sf.jasperreports.engine.fill.JRFillDataset.initDatasource(JRFillDataset.Java:667)      at net.sf.jasperreports.engine.fill.JRBaseFiller.setParameters(JRBaseFiller.Java:1253)      at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.Java:877)      at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.Java:822)      at net.sf.jasperreports.engine.fill.JRFiller.fill(JRFiller.Java:61)      at net.sf.jasperreports.engine.JasperFillManager.fill(JasperFillManager.Java:446)      at net.sf.jasperreports.engine.JasperFillManager.fill(JasperFillManager.Java:276)      at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.Java:745)      at com.jaspersoft.ireport.designer.compiler.IReportCompiler.run(IReportCompiler.Java:891)      at org.openide.util.RequestProcessor$Task.run(RequestProcessor.Java:572)      at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.Java:997)  Caused by: Java.sql.SQLException: Java.lang.NullPointerException      at com.hxtt.sql.dl.a(Unknown Source)      at com.hxtt.sql.c3.a(Unknown Source)      at com.hxtt.sql.aj.else(Unknown Source)      at com.hxtt.sql.aj.cm(Unknown Source)      at com.hxtt.sql.aj.s(Unknown Source)      at com.hxtt.sql.dl.a(Unknown Source)      at com.hxtt.sql.dl.a(Unknown Source)      at com.hxtt.sql.el.a(Unknown Source)      at com.hxtt.sql.dl.a(Unknown Source)      at com.hxtt.sql.br.a(Unknown Source)      at com.hxtt.sql.ai.a(Unknown Source)      at com.hxtt.sql.dn.executeQuery(Unknown Source)      at net.sf.jasperreports.engine.query.JRJdbcQueryExecuter.createDatasource(JRJdbcQueryExecuter.Java:239)      at net.sf.jasperreports.engine.fill.JRFillDataset.createQueryDatasource(JRFillDataset.Java:1086)      at net.sf.jasperreports.engine.fill.JRFillDataset.initDatasource(JRFillDataset.Java:667)      at net.sf.jasperreports.engine.fill.JRBaseFiller.setParameters(JRBaseFiller.Java:1253)      at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.Java:877)      at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.Java:822)      at net.sf.jasperreports.engine.fill.JRFiller.fill(JRFiller.Java:61)      at net.sf.jasperreports.engine.JasperFillManager.fill(JasperFillManager.Java:446)      at net.sf.jasperreports.engine.JasperFillManager.fill(JasperFillManager.Java:276)      at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.Java:745)      at com.jaspersoft.ireport.designer.compiler.IReportCompiler.run(IReportCompiler.Java:891)      at org.openide.util.RequestProcessor$Task.run(RequestProcessor.Java:572)      at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.Java:997)        at com.hxtt.global.SQLState.SQLException(Unknown Source)      at com.hxtt.sql.br.a(Unknown Source)      at com.hxtt.sql.ai.a(Unknown Source)      at com.hxtt.sql.dn.executeQuery(Unknown Source)      at net.sf.jasperreports.engine.query.JRJdbcQueryExecuter.createDatasource(JRJdbcQueryExecuter.Java:239)      ... 12 more  
Print not filled. Try to use an EmptyDataSource...

SQLでそれをどのように達成できますか?

1
BuZZ-dEE

このタイプのクエリは、派生テーブルまたは相関サブクエリを使用して、またはウィンドウ関数を備えた最新のDBMSで実行できます。一部のDBMSには、SQL-ServerのOUTER APPLYやPostgreSQLのDISTINCT ONなど、標準のSQL構文に特別な独自の拡張機能があり、この種の問題の解決にも使用できます。

FoxProにはこれらのいずれも含まれていないため、派生テーブルアプローチ、または私が呼ぶものを使用できます"poor man's OUTER APPLY"

SELECT 
    dh.r_art  AS documentHeadDocClass,
    fc.usd_brief AS foreignCurrencyUSDAsk,
    fc.usd_geld  AS foreignCurrencyUSDBid,
    fc.chf_brief AS foreignCurrencyCHFAsk,
    fc.chf_geld  AS foreignCurrencyCHFBid,
    fc.gbp_brief AS foreignCurrencyGBPAsk,
    fc.gbp_geld  AS foreignCurrencyGBPBid,
    fc.jpy_brief AS foreignCurrencyJPYAsk,
    fc.jpy_geld  AS foreignCurrencyJPYBid,
    dp.id   AS documentPeriodsID,
    dp.von  AS documentPeriodsFrom,
    dp.bis  AS documentPeriodsTo,
    dp.tage AS documentPeriodsDays,
    dp.rate AS documentPeriodsRate,
    dp.wert AS documentPeriodsWorth
FROM
        comperiode AS dp                 -- documentPeriods
    INNER JOIN 
        tckopf AS dh                     -- documentHead 
            ON dh.id = dp.id 
    LEFT OUTER JOIN
        devisen AS fc                    -- foreignCurrency
            ON fc.datum =
               ( SELECT TOP (1) fci.datum
                 FROM devisen AS fci
                 WHERE fci.datum <= dh.datum 
                 ORDER BY fci.datum DESC 
               )
WHERE 
        dh.id = $P{document_id} 
  AND   dp.id = $P{document_id} ;
2
ypercubeᵀᴹ

最後にON句を追加するのを忘れたと思います。

SELECT  documentHead.r_art AS documentHeadDocClass,
    foreignCurrency.usd_brief AS foreignCurrencyUSDAsk,
    foreignCurrency.usd_geld AS foreignCurrencyUSDBid,
    foreignCurrency.chf_brief AS foreignCurrencyCHFAsk,
    foreignCurrency.chf_geld AS foreignCurrencyCHFBid,
    foreignCurrency.gbp_brief AS foreignCurrencyGBPAsk,
    foreignCurrency.gbp_geld AS foreignCurrencyGBPBid,
    foreignCurrency.jpy_brief AS foreignCurrencyJPYAsk,
    foreignCurrency.jpy_geld AS foreignCurrencyJPYBid,
    documentListPeriods.id AS documentPeriodsID,
    documentListPeriods.von AS documentPeriodsFrom,
    documentListPeriods.bis AS documentPeriodsTo,
    documentListPeriods.tage AS documentPeriodsDays,
    documentListPeriods.rate AS documentPeriodsRate,
    documentListPeriods.wert AS documentPeriodsWorth
    FROM (
        SELECT  documentPeriods.id AS documentPeriodsID,
            documentPeriods.von AS documentPeriodsFrom,
            documentPeriods.bis AS documentPeriodsTo,
            documentPeriods.tage AS documentPeriodsDays,
            documentPeriods.rate AS documentPeriodsRate,
            documentPeriods.wert AS documentPeriodsWorth
        FROM comperiode AS documentPeriods
        WHERE documentPeriods.id = $P{document_id}
) AS documentListPeriods
INNER JOIN tckopf AS documentHead ON documentHead.id = $P{document_id}
LEFT OUTER JOIN (
    SELECT TOP 1
        fc.usd_brief AS foreignCurrencyUSDAsk,
        fc.usd_geld AS foreignCurrencyUSDBid,
        fc.chf_brief AS foreignCurrencyCHFAsk,
        fc.chf_geld AS foreignCurrencyCHFBid,
        fc.gbp_brief AS foreignCurrencyGBPAsk,
        fc.gbp_geld AS foreignCurrencyGBPBid,
        fc.jpy_brief AS foreignCurrencyJPYAsk,
        fc.jpy_geld AS foreignCurrencyJPYBidб
        fc.datum
    FROM
        devisen AS fс
    WHERE
        fc.datum <= $P!{exchangeRateTiming}
        AND fc.datum IS NOT NULL
        AND fc.usd_brief IS NOT NULL
        AND fc.usd_geld IS NOT NULL
        AND fc.chf_brief IS NOT NULL
        AND fc.chf_geld IS NOT NULL
        AND fc.gbp_brief IS NOT NULL
        AND fc.gbp_geld IS NOT NULL
        AND fc.jpy_brief IS NOT NULL
        AND fc.jpy_geld IS NOT NULL
    ORDER BY fc.datum DESC  ) AS foreignCurrency
ON foreignCurrency.datum = documentHead.datum

ところで、私はサブクエリの内部と外部でエイリアスを再利用するのは好きではありません。したがって、私はfcエイリアスを導入しました

0
cha