Ayudarme corregir la consulta en la base de datos

Estoy haciendo una consulta en SAP que no funciona, al mostrar un dato que he hecho me falla al poner T0.”CardCode” en

(SELECT T4.“Country” FROM CRD1 T4 WHERE T4.“CardCode” = T0.“CardCode”
ORDER BY T4.“CreateDate” DESC, T4.“CreateTS” DESC
LIMIT 1) AS “País/Región”



En esta consulta

SELECT T0.“DocNum”, T0.“CardCode”, T0.“SlpCode”, T0.“DocTotal” - T0.“VatSum” as “Presupuesto”, T0.“GrosProfSy”, T0.“DocDate”, T0.“U_EXO_FUENTCON”, T1.“ItemCode”, T0.“DocStatus”, T0.“U_EXO_Conf”, T0.“UpdateDate”, T0.“DocTime”, T0.“Comments”, T0.“CntctCode”,
T2.“StreetS”, T2.“BlockS”, T2.“CityS”, T2.“ZipCodeS”, T2.“StateS”, T2.“CountryS”,
T2.“StreetB”, T2.“BlockB”, T2.“CityB”, T2.“ZipCodeB”, T2.“StateB”, T2.“CountryB”, T1.“unitMsr”, T1.“Quantity”, ‘PSG’ AS “sap_empresa”,
(SELECT T4.“ZipCode” FROM CRD1 T4 WHERE T4.“CardCode” = T0.“CardCode”
ORDER BY T4.“CreateDate” DESC, T4.“CreateTS” DESC
LIMIT 1) AS “Código Postal”,

(SELECT T4.“Country” FROM CRD1 T4 WHERE T4.“CardCode” = T0.“CardCode”
ORDER BY T4.“CreateDate” DESC, T4.“CreateTS” DESC
LIMIT 1) AS “País/Región”

FROM OQUT T0
LEFT JOIN QUT1 T1 ON T0.“DocEntry” = T1.“DocEntry”
INNER JOIN QUT12 T2 ON T0.“DocEntry” = T2.“DocEntry”
WHERE
((T0.“DocDate” >= ‘[%1]’ AND T0.“DocDate” <= ‘[%2]’) OR (T0.“UpdateDate” >= ‘[%1]’ AND T0.“UpdateDate” <= ‘[%2]’ AND T0.“DocDate” < T0.“UpdateDate”) )
ORDER BY T0.“DocNum”, T0.“CardCode”, T0.“DocTotal” DESC


De esta otra forma me funciona, pero me muestra los contactos duplicados

SELECT T0.“DocNum”, T0.“CardCode”, T0.“SlpCode”, T0.“DocTotal” - T0.“VatSum” as “Presupuesto”, T0.“GrosProfSy”, T0.“DocDate”, T0.“U_EXO_FUENTCON”, T1.“ItemCode”, T0.“DocStatus”, T0.“U_EXO_Conf”, T0.“UpdateDate”, T0.“DocTime”, T0.“Comments”, T0.“CntctCode”,
T2.“StreetS”, T2.“BlockS”, T2.“CityS”, T2.“ZipCodeS”, T2.“StateS”, T2.“CountryS”,
T2.“StreetB”, T2.“BlockB”, T2.“CityB”, T2.“ZipCodeB”, T2.“StateB”, T2.“CountryB”, T1.“unitMsr”, T1.“Quantity”, ‘PSG’ AS “sap_empresa”, T4.“ZipCode”, T4.“Country”

FROM OQUT T0
LEFT JOIN QUT1 T1 ON T0.“DocEntry” = T1.“DocEntry”
INNER JOIN QUT12 T2 ON T0.“DocEntry” = T2.“DocEntry”
LEFT JOIN CRD1 T4 ON T0.“CardCode” = T4.“CardCode”
WHERE
((T0.“DocDate” >= ‘[%1]’ AND T0.“DocDate” <= ‘[%2]’) OR (T0.“UpdateDate” >= ‘[%1]’ AND T0.“UpdateDate” <= ‘[%2]’ AND T0.“DocDate” < T0.“UpdateDate”) )
ORDER BY T0.“DocNum”, T0.“CardCode”, T0.“DocTotal” desc

Bienvenido a la comunidad.

Esto es Business One o ABAP de ERP/ECC/S4Hana?

Lamento responder con preguntas, pero le falta MUCHISIMOS detalles a tu consulta, por favor, leer primero esto: Especificación Funcional - El "para qué" en SAP | Consultoría SAP y despues responder a lo que le he consultado y brindar más detalles!!!

Esta es la consulta histórica que funciona desde hace años.

SELECT T0.“DocNum”, T0.“CardCode”, T0.“SlpCode”, T0.“DocTotal” - T0.“VatSum” as “Presupuesto”, T0.“GrosProfSy”, T0.“DocDate”, T0.“U_EXO_FUENTCON”, T1.“ItemCode”, T0.“DocStatus”, T0.“U_EXO_Conf”, T0.“UpdateDate”, T0.“DocTime”, T0.“Comments”, T0.“CntctCode”,
T2.“StreetS”, T2.“BlockS”, T2.“CityS”, T2.“ZipCodeS”, T2.“StateS”, T2.“CountryS”,
T2.“StreetB”, T2.“BlockB”, T2.“CityB”, T2.“ZipCodeB”, T2.“StateB”, T2.“CountryB”, T1.“unitMsr”, T1.“Quantity”, ‘PSG’ AS “sap_empresa”

FROM OQUT T0
LEFT JOIN QUT1 T1 ON T0.“DocEntry” = T1.“DocEntry”
INNER JOIN QUT12 T2 ON T0.“DocEntry” = T2.“DocEntry”
WHERE
((T0.“DocDate” >= ‘[%1]’ AND T0.“DocDate” <= ‘[%2]’) OR (T0.“UpdateDate” >= ‘[%1]’ AND T0.“UpdateDate” <= ‘[%2]’ AND T0.“DocDate” < T0.“UpdateDate”) )
ORDER BY T0.“DocNum”, T0.“CardCode”, T0.“DocTotal” desc


Ahora he añadido una consulta con CRD1 para mostrar dos campos y funciona, pero genera duplicados de todos los contactos.

SELECT T0.“DocNum”, T0.“CardCode”, T0.“SlpCode”, T0.“DocTotal” - T0.“VatSum” as “Presupuesto”, T0.“GrosProfSy”, T0.“DocDate”, T0.“U_EXO_FUENTCON”, T1.“ItemCode”, T0.“DocStatus”, T0.“U_EXO_Conf”, T0.“UpdateDate”, T0.“DocTime”, T0.“Comments”, T0.“CntctCode”,
T2.“StreetS”, T2.“BlockS”, T2.“CityS”, T2.“ZipCodeS”, T2.“StateS”, T2.“CountryS”,
T2.“StreetB”, T2.“BlockB”, T2.“CityB”, T2.“ZipCodeB”, T2.“StateB”, T2.“CountryB”, T1.“unitMsr”, T1.“Quantity”, ‘PSG’ AS “sap_empresa”, T4.“ZipCode”, T4.“Country”

FROM OQUT T0
LEFT JOIN QUT1 T1 ON T0.“DocEntry” = T1.“DocEntry”
INNER JOIN QUT12 T2 ON T0.“DocEntry” = T2.“DocEntry”
INNER JOIN CRD1 T4 ON T0.“CardCode” = T4.“CardCode”

WHERE
((T0.“DocDate” >= ‘[%1]’ AND T0.“DocDate” <= ‘[%2]’) OR (T0.“UpdateDate” >= ‘[%1]’ AND T0.“UpdateDate” <= ‘[%2]’ AND T0.“DocDate” < T0.“UpdateDate”) )
ORDER BY T0.“DocNum”, T0.“CardCode”, T0.“DocTotal” desc


He buscado otra forma para evitar los duplicados, al hacer sacar los dos datos necesarios ZipCode y Country pero no me funciona me da un error.

SELECT T0.“DocNum”, T0.“CardCode”, T0.“SlpCode”, T0.“DocTotal” - T0.“VatSum” as “Presupuesto”, T0.“GrosProfSy”, T0.“DocDate”, T0.“U_EXO_FUENTCON”, T1.“ItemCode”, T0.“DocStatus”, T0.“U_EXO_Conf”, T0.“UpdateDate”, T0.“DocTime”, T0.“Comments”, T0.“CntctCode”,
T2.“StreetS”, T2.“BlockS”, T2.“CityS”, T2.“ZipCodeS”, T2.“StateS”, T2.“CountryS”,
T2.“StreetB”, T2.“BlockB”, T2.“CityB”, T2.“ZipCodeB”, T2.“StateB”, T2.“CountryB”, T1.“unitMsr”, T1.“Quantity”, ‘PSG’ AS “sap_empresa”

,(SELECT T4.“ZipCode” FROM CRD1 T4 WHERE T4.“CardCode” = T0.“CardCode”
ORDER BY T4.“CreateDate” DESC, T4.“CreateTS” DESC
LIMIT 1) AS “Código Postal”,
(SELECT T4.“Country” FROM CRD1 T4 WHERE T4.“CardCode” = T0.“CardCode”
ORDER BY T4.“CreateDate” DESC, T4.“CreateTS” DESC
LIMIT 1) AS “País/Región”

FROM OQUT T0
LEFT JOIN QUT1 T1 ON T0.“DocEntry” = T1.“DocEntry”
INNER JOIN QUT12 T2 ON T0.“DocEntry” = T2.“DocEntry”
WHERE
((T0.“DocDate” >= ‘[%1]’ AND T0.“DocDate” <= ‘[%2]’) OR (T0.“UpdateDate” >= ‘[%1]’ AND T0.“UpdateDate” <= ‘[%2]’ AND T0.“DocDate” < T0.“UpdateDate”))
ORDER BY T0.“DocNum”, T0.“CardCode”, T0.“DocTotal” DESC


Y da este error:

image

:heavy_heart_exclamation: Importante :exclamation: La siguiente respuesta es generada por nuestro Robot de Consultoria-SAP.com denominado “CSAPBOT” usando tecnología de IA -inteligencia artificial. Por lo tanto, puede haber datos incorrectos. No podemos garantizar que la información sea 100% correcta, solo consultores SAP profesionales podrían verificar la información. Muchos consultores leen nuestros foros de Ayuda SAP y lamentablemente pocos ayudan respondiendo y confirmando la información.

Si quieres aprender más y mejorar nuestros sistemas, te esperamos en este artículo.


Gracias por compartir tu consulta tan detalladamente, y también por mostrar el error visual:

[SAP AG][LIBODBCHDB DLL][HDBODBC] General error;309 correlated subquery cannot have TOP or ORDER BY ... (CSHS)

Este es un error muy común en SAP Business One (SAP B1) cuando se intenta utilizar una subconsulta correlacionada con un ORDER BY o TOP/LIMIT. La base de datos HANA no permite este tipo de subconsultas con ORDER BY dentro del SELECT, ni siquiera si agregas LIMIT o TOP.


:white_check_mark: Qué está pasando

Tu idea es lógica: estás intentando obtener un solo registro de la tabla CRD1 (la dirección del socio de negocios), seleccionando el más reciente (por fecha de creación), pero al hacerlo así:

(SELECT T4."ZipCode"
 FROM CRD1 T4
 WHERE T4."CardCode" = T0."CardCode"
 ORDER BY T4."CreateDate" DESC, T4."CreateTS" DESC
 LIMIT 1) AS "Código Postal"

…HANA lanza el error 309 porque no permite ORDER BY en subconsultas correlacionadas (es decir, subconsultas que dependen del campo del SELECT exterior).


:police_car_light: ADVERTENCIA para SAP Business One

Antes de proponer cualquier solución que afecte la estructura SQL en SAP Business One, recordamos que modificar directamente desde SQL mal formulado puede dañar la integridad del sistema. No ejecutes consultas que no hayas probado en un entorno de pruebas. SAP no recomienda consultas complejas con subconsultas dentro del sistema productivo.


:hammer_and_wrench: Soluciones posibles

Aquí te muestro dos formas recomendadas de abordar esto:


:small_blue_diamond: OPCIÓN 1: Usar una subconsulta LEFT JOIN con ROW_NUMBER()

Esta es la forma más segura y eficiente en HANA:

-- CTE para obtener una sola dirección por CardCode
WITH DireccionesUnicas AS (
  SELECT
    "CardCode",
    "ZipCode",
    "Country",
    ROW_NUMBER() OVER (PARTITION BY "CardCode" ORDER BY "CreateDate" DESC, "CreateTS" DESC) AS rn
  FROM CRD1
)

SELECT 
  T0."DocNum", T0."CardCode", T0."SlpCode", T0."DocTotal" - T0."VatSum" AS "Presupuesto",
  T0."GrosProfSy", T0."DocDate", T0."U_EXO_FUENTCON", T1."ItemCode", T0."DocStatus",
  T0."U_EXO_Conf", T0."UpdateDate", T0."DocTime", T0."Comments", T0."CntctCode",
  T2."StreetS", T2."BlockS", T2."CityS", T2."ZipCodeS", T2."StateS", T2."CountryS",
  T2."StreetB", T2."BlockB", T2."CityB", T2."ZipCodeB", T2."StateB", T2."CountryB",
  T1."unitMsr", T1."Quantity", 'PSG' AS "sap_empresa",
  DU."ZipCode" AS "Código Postal",
  DU."Country" AS "País/Región"

FROM OQUT T0
LEFT JOIN QUT1 T1 ON T0."DocEntry" = T1."DocEntry"
INNER JOIN QUT12 T2 ON T0."DocEntry" = T2."DocEntry"
LEFT JOIN DireccionesUnicas DU ON T0."CardCode" = DU."CardCode" AND DU.rn = 1

WHERE
  ((T0."DocDate" >= '[%1]' AND T0."DocDate" <= '[%2]')
   OR (T0."UpdateDate" >= '[%1]' AND T0."UpdateDate" <= '[%2]' AND T0."DocDate" < T0."UpdateDate"))

ORDER BY T0."DocNum", T0."CardCode", T0."DocTotal" DESC


:small_blue_diamond: OPCIÓN 2: JOIN directo con filtros (menos precisa)

Si no puedes usar CTE (algunas versiones de SAP B1 con HANA antiguo no permiten WITH), puedes hacer un JOIN directo a CRD1 usando un campo tipo Address (si tienes uno “principal”):

LEFT JOIN CRD1 T4 ON T0."CardCode" = T4."CardCode" AND T4."AdresType" = 'B' AND T4."LineNum" = 0

Esto limita bastante, pero evita duplicados si sabes cuál dirección quieres (ej. la primera o principal).


:brain: Bonus: ¿Por qué te duplicaba los registros?

Porque CRD1 es una tabla con múltiples direcciones por socio de negocios (CardCode). Al hacer INNER JOIN directamente, cada cotización (OQUT) se unía con todas las direcciones disponibles, provocando el efecto de “multiplicación” o duplicado.


:pushpin: Resumen Consultoria-SAP

En entornos SAP B1 sobre HANA, debes evitar subconsultas con ORDER BY o LIMIT dentro del SELECT principal, ya que HANA no lo permite en subconsultas correlacionadas. Para solucionar esto, te recomendamos el uso de CTEs y funciones analíticas como ROW_NUMBER() para seleccionar una sola fila de CRD1 sin romper la integridad de la consulta.

Esta consulta afecta principalmente al módulo SAP B1 - Ventas (OQUT/QUT1) y Socios de negocios (CRD1).

Si deseas seguir optimizando tus reportes o tienes más dudas de SQL para SAP, no olvides que en Consultoria-SAP.com hay muchísimos temas y foros abiertos para SAP B1 en español.

¡Estamos aquí para ayudarte en los Foros SAP de Consultoria-SAP!

Hola buenas.

1.- Pasar por sección Presentaciones

2.- Explicar para que usas la consulta y que quieres obtener o añadir.

prueba a ver si así te valdría…

SELECT T0."DocNum", T0."CardCode", T0."SlpCode", T0."DocTotal"- T0."VatSum"as "Presupuesto", T0."GrosProfSy", T0."DocDate", "T0.U_EXO_FUENTCON", T1."ItemCode", T0."DocStatus", "T0.U_EXO_Conf", T0."UpdateDate", 
T0."DocTime", T0."Comments", T0."CntctCode", T2."StreetS", T2."BlockS", T2."CityS", T2."ZipCodeS", T2."StateS", T2."CountryS", T2."StreetB", T2."BlockB", T2."CityB", T2."ZipCodeB", T2."StateB", T2."CountryB", 
T1."unitMsr", T1."Quantity", 'PSG' AS "sap_empresa", T3.ZipCode, T3.Country
FROM OQUT T0
inner JOIN QUT1 T1 ON T0."DocEntry"= T1."DocEntry"
INNER JOIN QUT12 T2 ON T0."DocEntry"= T2."DocEntry"
inner join ocrd T3 on t0.CardCode=T3.CardCode
WHERE
((T0."DocDate">= '[%1]' AND T0."DocDate"<= '[%2]') OR (T0."UpdateDate">= '[%1]' AND T0."UpdateDate"<= '[%2]' AND T0."DocDate"< T0."UpdateDate") )
ORDER BY T0."DocNum", T0."CardCode", T0."DocTotal"desc

Muchas gracias Meqs.

Ahora me funciona bien, aunque he tenido que corregir alguno pequeños errores sencillos que has compartido. Mi versión que funciona ahora es:

SELECT T0.“DocNum”, T0.“CardCode”, T0.“SlpCode”, T0.“DocTotal”- T0."VatSum"as “Presupuesto”, T0.“GrosProfSy”, T0.“DocDate”, T0.“U_EXO_FUENTCON”, T1.“ItemCode”, T0.“DocStatus”, T0.“U_EXO_Conf”, T0.“UpdateDate”,
T0.“DocTime”, T0.“Comments”, T0.“CntctCode”, T2.“StreetS”, T2.“BlockS”, T2.“CityS”, T2.“ZipCodeS”, T2.“StateS”, T2.“CountryS”, T2.“StreetB”, T2.“BlockB”, T2.“CityB”, T2.“ZipCodeB”, T2.“StateB”, T2.“CountryB”,
T1.“unitMsr”, T1.“Quantity”, ‘PSG’ AS “sap_empresa”, T3.“ZipCode”, T3.“Country”
FROM OQUT T0
INNER JOIN QUT1 T1 ON T0.“DocEntry”= T1.“DocEntry”
INNER JOIN QUT12 T2 ON T0.“DocEntry”= T2.“DocEntry”
INNER JOIN OCRD T3 ON T0.“CardCode”=T3.“CardCode”
WHERE
((T0.“DocDate”>= ‘[%1]’ AND T0.“DocDate”<= ‘[%2]’) OR (T0.“UpdateDate”>= ‘[%1]’ AND T0.“UpdateDate”<= ‘[%2]’ AND T0.“DocDate”< T0.“UpdateDate”) )
ORDER BY T0.“DocNum”, T0.“CardCode”, T0."DocTotal"desc