Подзапросы Crystal Reports - PullRequest
       9

Подзапросы Crystal Reports

1 голос
/ 14 января 2010

Мне нужно создать отчет, который ссылается на несколько таблиц, в том числе одну таблицу, которая является построчной деталью заказа. По заказам у нас есть пакеты, и единственный способ определить, имеет ли пакет определенный статус, - это проанализировать статусы его компонентов. Детали счета хранятся в последовательном порядке с номером строки и уровнем элемента каждой строки. Записи с уровнем элемента> 1 являются частями наборов, которые непосредственно предшествуют им. Так, например ::

Invoiceiid | Lineno | LevelNo | SKU
----------------------------------------------------
10192      | 1      | 1       | K-PACKAGE
10192      | 2      | 2       | SCREEN
10192      | 3      | 2       | CABLE
10192      | 4      | 1       | LCD PROJECTOR

В этом примере ЭКРАН и КАБЕЛЬ являются частью K-ПАКЕТА, а ЖК-ПРОЕКТОР - нет.

Я изменяю статус этих пакетов в зависимости от состояния их составных частей. Для моих целей среднее из статусов работает нормально. У меня есть команда, включенная ниже, в качестве уменьшенной версии SQL-запроса, который я использую (более крупная версия - это просто грубый метод для обработки нескольких количеств подпунктов). Команда принята на экране Эксперта базы данных, окно «Редактировать команду», но на самом деле при попытке предварительного просмотра отчета возвращается

"Ошибка соединителя базы данных: 'HY000: [Oracle] [ODBC] [Ora] ORA-01427: однострочный подзапрос возвращает более одной строки [Код поставщика базы данных: 1427]'"

когда он действительно начинает пытаться получить результаты.

Вот урезанный SQL-запрос, который я использую, чтобы попытаться найти проблему. Сейчас я показываю только профит-центр, чтобы попытаться выяснить, не в этом ли проблема.

select ih.billdate, ih.invoiceid, ih.profitcenter, co.contractid, il.action,
(
      case il.status
            when 15 then
            (
                  case when (((select il2.itemlevel from invoiceline il2 where il2.invoiceiid = il.invoiceiid and il2.lineno = (il.lineno + 1)) = 1) or ((select count(il2.itemlevel) from invoiceline il2 where il2.invoiceiid = il.invoiceiid and il2.lineno = (il.lineno + 1)) = 0))
                        then 15
                  when (((select max(il2.lineno) from invoiceline il2 where il2.invoiceiid = il.invoiceiid) <= (il.lineno + 2)))
                        then (select il5.status from invoiceline il5 where il5.invoiceiid = il.invoiceiid and il5.lineno = (il.lineno + 1))
                  else
                        15
                  end
            )
            else
                  il.status
      end
      ) as "Status",
il.amount, il.discountamount, im.revenuegroup, im.subrentalexpense, im.discountgroup, im.subrentglcode, im.sellglcode from invoicehead ih inner join contract co on ih.contractiid = co.contractiid left outer join invoiceline il on ih.invoiceiid = il.invoiceiid inner join invmaster im on il.inviid = im.invi

Если я изменюсь

then (select il5.status from invoiceline il5 where il5.invoiceiid = il.invoiceiid and il5.lineno = (il.lineno + 1))

Чтобы указать строгое число (например, 15), предварительный просмотр отчета без проблем.

И просто для ясности: на самом деле нет никакой другой ссылки (по крайней мере, я не могу найти) между основным элементом пакета и компонентами, а также я не могу изменить схему базы данных. И все должно быть в Crystal Reports.

Есть мысли?

Ответы [ 2 ]

1 голос
/ 14 января 2010

Похоже, что у вас есть записи с одинаковыми (Invoiceiid, Lineno), вы можете проверить с помощью следующего запроса:

SELECT invoiceiid, lineno, COUNT(*)
  FROM invoiceline
 GROUP BY invoiceiid, lineno
HAVING COUNT(*) > 1

Если это так, я бы предложил вам исправить ваши данные, а затем добавить УНИКАЛЬНОЕ ОГРАНИЧЕНИЕ на (Invoiceiid, Lineno)

Обновление

@ Майкл: в ответ на ваш комментарий: ЕСЛИ вы не можете исправить данные, вам придется решать, что делать, если вы обнаружите дубликаты. Например, вы можете изменить подзапросы il2 и il5, чтобы они возвращали не более одной строки , например, заменить SELECT il2.itemlevel на SELECT MAX(il2.itemlevel).

Вы также можете использовать аналитику, чтобы прочитать значение следующей строки (это будет более эффективно, чем подзапрос):

SELECT ih.billdate, ih.invoiceid, ih.profitcenter, co.contractid, il.action,
       (CASE il.status
          WHEN 15 THEN
           (CASE
              WHEN LEAD(il2.itemlevel) OVER(PARTITION BY invoiceiid ORDER BY lineno) IS NULL THEN
               15
              WHEN MAX(il2.lineno) OVER(PARTITION BY invoiceiid) <= il.lineno + 2 THEN
               LEAD(il5.status) OVER(PARTITION BY invoiceiid ORDER BY lineno)
              ELSE
               15
           END)
          ELSE
           il.status
       END) AS "Status", il.amount, il.discountamount, im.revenuegroup, im.subrentalexpense, im.discountgroup,
       im.subrentglcode, im.sellglcode
  FROM invoicehead ih
 INNER JOIN contract co ON ih.contractiid = co.contractiid
  LEFT OUTER JOIN invoiceline il ON ih.invoiceiid = il.invoiceiid
 INNER JOIN invmaster im ON il.inviid = im.invi
0 голосов
/ 14 января 2010

Благодаря Винсенту ... оказывается, для этого было две разные причины. Во-первых, как указал Винсент, у меня были повторяющиеся записи, и я смог их починить.

Другая проблема заключалась в том, что я предполагал, что значения NULL достигли 0 (в данном случае они этого не сделали), и мои границы не были установлены правильно. После корректировки условий исключения я смог заставить работать код. Большое спасибо!

...