Left outer Join in Cube JS - mysql

I have a requirement to join two tables in cube js. First table has list of customers. Second table has list orders with customer ids with purchase date. I have to display the total orders placed by the customer with date filter. If the there is an order available in the second table I am able to get the customer row with the order count. If the date range is changed and if no orders available it should show zero against customer, instead no row is returned.
Any work around or help on this is much appreciated.

you could specify the left outer join in the SQL property of the cube:
cube(`Users`, {
sql: `SELECT * from orders LEFT OUTER JOIN customers,
})
In your dimensions specify a new dimension that takes 1 if order id is not null and takes 0 else, as follows:
hasOrder: {
type: `number`,
case: {
when: [
{ sql: `${CUBE}.order_id is null`, label: { sql: Number("0") } },
{ sql: `${CUBE}.order_id is not null`, label: { sql: Number("1") } }
],
}
},
then define a measure that sums the number of Orders, it should return O for customers with no orders:
measures: {
ordersCompletedCount: {
type: `sum`,
sql: `${CUBE.hasOrder}`
},
},

Related

Postgresql JSON Sql coding

How to write JSON SQL coding for the below json data:
{
"orderSystem":"SAP",
"orderHeader":{
"salesDoc":"0011214280",
"soldTo":"0000089890",
"createDate":"2020-01-02",
"purchNo":"2020-00-16213",
"billingStatus":"billed",
"ecomStatus":"Complete/Invoiced",
"purchDate":"2020-01-02",
"netValHd":"33416.500000000",
"taxesHd":"0.000000000",
"currency":"USD"
},
"orderItems":[
{
"docNumber":"0011214280",
"itmNumber":"000100",
"netValue":"33416.500000000",
"currency":"USD",
"shipments":[
{
"docNumber":"0011214280",
"itmNumber":"000100",
"scheduleLine":"0001",
"material":"000000000016121362"
}
]
}
],
"invoices":[
{
"billingDoc":"0048471944",
"docCategory":"M",
"currency":"USD",
"status":"CLOSED",
"invoiceUrl":"/ZSD_BILLING_API_GET_PDF"
}
]
}
Here "orderSystem":"SAP" is hard coded value. Then all "orderHeader" tags are from sales_order table. "orderItems" tags from sales_order_item table. "shipments" are from sales_order_shipment table. "invoices" are from invoice table.
sales_order table have single record for an order.
sales_order_item table may have multiple records for an order.
sales_order_shipment table may have multiple records for an order.
invoices table may have multiple records for an order.
Here joining column for all table is "salesDoc" column. How to achieve it sql json query?
Example i am giving input as salesDoc data. Then i need to pull the data in the above json format.
Here is the answer,
select row_to_json(tab)
from (
select 'SAP' sourceSystem,
(
select row_to_json(od)
from (
select sales_order_header.salesDoc,sales_order_header.soldTo,sales_order_header.createDate,sales_order_header.purchNo,sales_order_header.billingStatus,sales_order_header.ecomStatus,sales_order_header.purchDate,sales_order_header.netValHd,sales_order_header.taxesHd,sales_order_header.currency
) od
) as orderHeader,
(select array_to_json(array_agg(row_to_json(li))) from (
select sales_order_line.docNumber,sales_order_line.itmNumber,sales_order_line.netValue,sales_order_line.currency from
ecommerce.sales_order_line sales_order_line where sales_order_header.sales_ordr_no = sales_order_line.sales_ordr_no) li )as orderItems,
(select array_to_json(array_agg(row_to_json(ss))) from (
select shipment.docNumber,shipment.itmNumber,shipment.scheduleLine,shipment.material
from ecommerce.sales_order_shipment shipment where sales_order_header.sales_ordr_no = sales_order_shipment.sales_ordr_no) ss )as shipments,
(select array_to_json(array_agg(row_to_json(iv))) from (
select invoices.billingDoc,invoices.docCategory,invoices.currency ,invoices.status, invoices.invoiceUrl
from ecommerce.sales_order_invoices invoices where sales_order_header.sales_ordr_no = invoices.sales_ordr_no) iv )as invoices,
from ecommerce.sales_order_header as sales_order_header
) tab
I went through the below link and it was very useful for my case
https://hashrocket.com/blog/posts/faster-json-generation-with-postgresql

Sequelize findAll where a column value is the same as at least one other item in table

I currently have the below query which is getting everything that has id = a certain value, but I need it to get only items that have a their column (called Uid) value appear more than once in the table.
Basically I need to filter out items with a unique Uid column value from the result of the below query
models.table.findAll({
where:{
id: req.params.id
}
})
So I believe the SQL query you're looking for would be
SELECT id, uid, count(*) FROM table
WHERE id = :id
GROUP BY id, uid
HAVING count(uid) > 1;
And in Sequelize it would be:
models.table.findAll({
where: { id: req.params.id },
group: ['id', 'uid'],
having: [sequelize.literal('count(?) > ?)', 'uid', 1]
})
Not entirely sure if that is the right syntax for Sequelize. Also look at sequelize.fn() and sequelize.col().

Sum results of multiple grouped documents

I have setup a schema where I associate two different entities: Users and Brands. This association is stored in the document UserBrand. A user may have multiple brands, and in each UserBrand document, the information there contained is different.
Here is an example of three documents:
{
type: "UserBrand",
userId: "x",
brandId: 1,
value: 100
}
{
type: "UserBrand",
userId: "x",
brandId: 2,
value: 50
}
{
type: "UserBrand",
userId: "y",
brandId: 1,
value: 150
}
As you see, user 'x' follows multiple brands. How can I get the sum of the values grouped by user, while fetching the user information as well?
So far I am able to join both document types (User and UserBrand) through this query:
SELECT ub.*, u.name FROM bucket as ub JOIN bucket as u ON KEYS "User_" || ub.userId WHERE ub.type="UserBrand" AND u.type="User" AND (ub.brand=1 OR ub.brand=2)
but I cannot seem to group the records and sum the values for a single user. Is it possible to do so on a single query?
If possible, the end result should be something like:
{
type: "UserBrand",
name: "name1',
userId: "x",
brandId: 1,
value: 150
}
{
type: "UserBrand",
name: "name2',
userId: "y",
brandId: 1,
value: 150
}
Why are you using 'join' instead of simply 'group by' and aggregation? If I wanted to sum the values for each distinct userId, I would write a query as follows:
select userId, sum(value) from bucket group by userId;
Note that when using 'group by', every field in the select list must be either part of the 'group by' list (userId above) or an aggregation expression (like sum(value) above). But what if you want to include the field 'name' in the result? If you know that 'name' always has the same value for a given id, you could use an aggregation function like 'max' or 'min' to bring up the value (since max of a set of identical values will be any of the values):
select userId, max(name), sum(value) from bucket group by userId;
For a field like 'brandId', which seems to have different values, you'd want to use an aggregation function like 'array_agg', which will take all the different values of 'brandId' and put them in an array. E.g.,
select userId, max(name), sum(value), array_agg(distinct brandId) from bucket group by userId;

MDX Crossjoin Region and Country and grand total

I need to join two hierarchies, Region and Country. From our Cube I have to get a result consisting of 1 region and 2 countries. This is what i've done so far:
SET [RegionSet] AS
{
[Stores].[Region].&[EUROPE]
}
SET [CountrySet] AS
{
[Stores].[Country].&[Japan]&[APAC]
,[Stores].[Country].&[China]&[APAC]
}
NON EMPTY
(
{
[RegionSet]
, [Stores].[Region].[All]
}
)
* (
{
[CountrySet]
, [Stores].[Country].[All]
}
)
ON ROWS
The MSD result is following:
But I want to list the region and countries in one column without the All entries and add a grand total to the last row. How can I do this?
I think if you had a multi-level user hierarchy called [Geography] as part of the [Stores] dimension then I think it would be trivial:
SET [RegionCountrySet] AS
{
[Stores].[Geography].[Region].&[EUROPE]
,[Stores].[Geography].[Country].&[Japan]&[APAC]
,[Stores].[Geography].[Country].&[China]&[APAC]
}
...but you can create custom aggregated members. Then use the created members on rows:
Pick a unused hierarchy to "host" your new members in. I will assume you have a [Languages] dimension. The new members are added as children to the [All] member of your chosen hierarchy.
Create tuples from the targets including the hosts [All] member in each of the tuples.
Like this
MEMBER [Languages].[Language].[All].[EUROPE] AS
(
[Languages].[Language].[All]
,[Stores].[Region].&[EUROPE]
)
MEMBER [Languages].[Language].[All].[Japan] AS
(
[Languages].[Language].[All]
,[Stores].[Country].&[Japan]&[APAC]
)
MEMBER [Languages].[Language].[All].[China] AS
(
[Languages].[Language].[All]
,[Stores].[Country].&[China]&[APAC]
)
SET [S1] AS
{
[Languages].[Language].[All].[EUROPE]
,[Languages].[Language].[All].[Japan]
,[Languages].[Language].[All].[China]
}
MEMBER [Languages].[Language].[All].[Grand Total] AS
Aggregate([S1])
SET [S2] AS
{
[Languages].[Language].[All].[EUROPE]
,[Languages].[Language].[All].[Japan]
,[Languages].[Language].[All].[China]
,[Languages].[Language].[All].[Grand Total]
}
Then in the script try this
[S2] ON ROWS

Get all records from a table along with a selected record in single MySQL query statement

I'm pretty bad when it comes to designing database queries, can I have some help?
Here are the 2 tables (samples):
TABLE user: id, name, relationship_type_id
TABLE relationship_type: relationship_type_id (fk), relationship, contributing
Now, I want to use a single query to get:
All the relationship_type table's records (i.e. SELECT * FROM relationship_type)
And the specific relationship of the user who has id = 5
So the result is something like this (assuming table relationship_type has only 2 records)
"data": [
{
"relationship": "Friend" // for user id = 5
},
{
"relationship_type_id": "1"
"relationship": "Partner"
},
{
"relationship_type_id": "2"
"relationship": "Friend"
}
],
SELECT user.id, user.name
FROM user
LEFT JOIN relationship_type
ON user.relationship_type_id=relationship_type.relationship_type_id WHERE user.id=5;
SELECT
rt.*, u.*
FROM
relationship_type rt
LEFT JOIN
user u
ON rt.relationship_type_id = u.relationship_type_id
WHERE
u.id = 5
UNION
SELECT *
FROM relationship_type;