Resolver consultas que no se deberían haber dividido

Si las consultas están divididas pero no se deberían haber dividido, deberá resolverlas.

Los asuntos de consulta en la parte n de todas las relaciones se identifican como hechos. Puede observarse que, en el siguiente ejemplo, Order Header y Country Multilingual se comportan como hechos. En realidad, el asunto de consulta Country Multilingual contiene sólo información descriptiva y parece una tabla de búsqueda. Desde una perspectiva dimensional o de modelado empresarial, Country Multilingual es una extensión de Country.

¿Por qué supone un problema dejar el modelo así?

Modelo que muestra consultas divididas

Pruebe este modelo mediante la creación de un informe sobre el número de pedidos por ciudad y por país o región. Al utilizar este modelo, se devuelve un resultado incorrecto. Los números son correctos para las ciudades pero algunas de éstas se muestran en el país o región equivocado. Este es un ejemplo de un resultado relacionado incorrecto.

Salida de informe de lista de consulta dividida

Normalmente, el primer lugar que hay que analizar cuando se observa un resultado como éste es el SQL.

SQL

En este ejemplo, se ve una consulta enlazada, que tiene sentido si hay hechos múltiples en el modelo. Una consulta enlazada es esencialmente una consulta que intenta unir hechos múltiples. Utiliza las relaciones que relacionan los hechos entre sí, así como los determinantes para las dimensiones compatibles, o comunes, definidas en el modelo. Una consulta enlazada se puede identificar mediante dos consultas con una unión externa completa. La consulta wrapper debe incluir una sentencia coalesce sobre las dimensiones compatibles.

Tenga en cuenta los siguientes problemas del SQL:

  • La consulta no tiene ninguna sentencia coalesce.
  • RSUM indica un intento de crear una clave válida.
select 
	D3.COUNTRY as COUNTRY, 
	D2.CITY as CITY, 
	D2.number_of_orders as number_of_orders 
from 
(select 
	SALES_BRANCH.CITY as CITY,
	XCOUNT(ORDER_HEADER.ORDER_NUMBER for SALES_BRANCH.CITY) as
	number_of_orders,
	RSUM(1 at SALES_BRANCH.CITY order by SALES_BRANCH.CITY
asc local)  
	as sc  
	from  
	gosales.gosales.dbo.SALES_BRANCH SALES_BRANCH
	join 
	gosales.gosales.dbo.ORDER_HEADER ORDER_HEADER
	on (SALES_BRANCH.SALES_BRANCH_CODE = ORDER_HEADER.SALES_BRANCH_CODE)
group by 
	SALES_BRANCH.CITY
order by 
	CITY asc
	) D2
full outer join 
(select 
	COUNTRY_MULTILINGUAL.COUNTRY as COUNTRY,
	RSUM(1 at COUNTRY_MULTILINGUAL.COUNTRY order by
	COUNTRY_MULTILINGUAL.COUNTRY asc local) as sc
from 
	gosales.gosales.dbo.COUNTRY_MULTILINGUAL COUNTRY_MULTILINGUAL
group by 
	COUNTRY_MULTILINGUAL.COUNTRY
order by 
	COUNTRY asc
	) D3
	on (D2.sc = D3.sc)

Si se analizan las columnas enlazadas en cada consulta, se observa que se están calculando según criterios no relacionados. Esto explica por qué no existe una relación aparente entre los países/regiones y las ciudades del informe.

¿Por qué hay una consulta enlazada? Para responder a esta pregunta hay que analizar el modelo.

En este ejemplo, los elementos de consulta utilizados en el informe provenían de asuntos de consulta diferentes. Country or region provenía de Country Multilingual, City provenía de Sales Branch y Number of Orders provenía de un recuento de Order Number del asunto de consulta Order Header.

Diagrama del modelo de los asuntos de consulta Country Multilingual, Country, Sales Branch y Order Header

El problema es que la consulta se divide porque el motor de consultas la considera una consulta sobre varios hechos. Sin embargo, la división no tiene una clave válida a la que enlazarse porque no existe un elemento común a los dos hechos.

Existe más de una forma de resolver este problema pero en ambos casos es necesario conocer los datos.

Solución 1

Puede añadir un filtro a Country Multilingual que cambie la cardinalidad de la relación a 1-1.

Select *
from [GOSL].COUNTRY_MULTILINGUAL
Where
COUNTRY_MULTILINGUAL."LANGUAGE"='EN'

O bien, puede añadir un filtro a la relación y cambiar la cardinalidad a 1-1.

COUNTRY.COUNTRY_CODE = COUNTRY_MULTILINGUAL.COUNTRY_CODE
and COUNTRY_MULTILINGUAL.LANGUAGE = 'EN'

Con ambas opciones, se genera un modelo que tiene un hecho único en esta consulta.

Solución 2

Simplifique el modelo mediante la consolidación de los asuntos de consulta relacionados. Ésta es la mejor solución porque simplifica el modelo y reduce las posibilidades de que se produzca un error al generar la consulta.

Diagrama del modelo de asuntos de consulta Sales Branch y Order Header con asunto de consulta New Country or region como consolidación de Country y Country Multilingual

Ahora, con cualquiera de las dos soluciones, se obtiene una consulta correcta.

Salida de informe de lista

El SQL ya no es una consulta enlazada.

select 
	Country.c7 as COUNTRY,
	SALES_BRANCH.CITY as CITY,
	XCOUNT(ORDER_HEADER.ORDER_NUMBER for Country.c7,SALES_BRANCH.CITY)
	as number_of_orders
from 
(select 
	COUNTRY.COUNTRY_CODE as c1,
	COUNTRY_MULTILINGUAL.COUNTRY as c7
from 
	gosales.gosales.dbo.COUNTRY COUNTRY
	join 
	gosales.gosales.dbo.COUNTRY_MULTILINGUAL COUNTRY_MULTILINGUAL
	on (COUNTRY.COUNTRY_CODE = COUNTRY_MULTILINGUAL.COUNTRY_CODE)
	where COUNTRY_MULTILINGUAL.LANGUAGE='EN'
	) Country
join 
	gosales.gosales.dbo.SALES_BRANCH SALES_BRANCH
	on (SALES_BRANCH.COUNTRY_CODE = Country.c1)
	join
	gosales.gosales.dbo.ORDER_HEADER ORDER_HEADER
	on (SALES_BRANCH.SALES_BRANCH_CODE = ORDER_HEADER.SALES_BRANCH_CODE)
group by 
	Country.c7,
	SALES_BRANCH.CITY