0

I have the following table in Google Cloud Spanner for categories.

CREATE TABLE categories (
  categoryId STRING(36) NOT NULL,
  name STRING(128) NOT NULL,
  parent BOOL NOT NULL,
  parentId STRING(36),
  archived BOOL,
  FOREIGN KEY (parentId) REFERENCES categories (categoryId)
) PRIMARY KEY(categoryId);

So the table might have entries as shown below.

categoryId name parent parentId archived
1 Clothing true false
2 Homeware true false
3 Shirts false 1 false
4 Pants false 1 false
5 Technology true false
6 Tablets false 5 true

I want to query this table such that it returns firstly all the parent categories that aren't archived (I can't really delete rows in my application, as documents will reference rows - so I implemented archiving), along with all the child categories (not archived) belonging to said parents.

I came as far as writing the following query:

SELECT categories.categoryId, categories.name, childCategories.name AS childName 
FROM categories
LEFT JOIN categories AS childCategories
ON childCategories.parentId = categories.categoryId
WHERE categories.parent = true AND categories.archived = FALSE

However, this will return rows where child categories are archived. Below is the exact result returned.

categoryId name childName
1 Clothing Shirts
1 Clothing Pants
2 Homeware
5 Technology Tablets

The desired result would be:

categoryId name childName
1 Clothing Shirts
1 Clothing Pants
2 Homeware
5 Technology

I have tried altering the query as:

SELECT categories.categoryId, categories.name, childCategories.name AS childName 
FROM categories
LEFT JOIN categories AS childCategories
ON childCategories.parentId = categories.categoryId
WHERE categories.parent = true AND categories.archived = FALSE AND childCategories.archived = FALSE

This, however, won't return any parent categories if they don't have at least one child category. Below is the exact result returned.

categoryId name childName
1 Clothing Shirts
1 Clothing Pants

I can't figure out how to write the query to obtain the desired result. Any help/insight would be appreciated. Thanks in advance!

1
  • 1
    Almost there, Move this childCategories.archived = FALSE to the ON condition instead of Where. Commented May 25, 2022 at 8:52

1 Answer 1

3

You were almost there, as you need only the child Categories which are not archived, Move the condition childCategories.archived = FALSE to ON instead of WHERE clause.

Putting the filter on WHERE will remove the result from Dataset, however if you put it in ON condition, will return everything from parent Categories and respective matching row from Child.

SELECT categories.categoryId, categories.name, childCategories.name AS childName 
FROM categories
LEFT JOIN categories AS childCategories
ON childCategories.parentId = categories.categoryId
AND childCategories.archived = FALSE --Added here
WHERE categories.parent = true AND categories.archived = FALSE 
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.