Date: prev next · Thread: first prev next last
2016 Archives by date, by thread · List index


Hi Don,

Your SELECT statement is indeed incorrect; it seems as though you don't
fully understand joins (I could be mistaken, but your syntax is off
by enough to suggest this).

Firstly, choose a format for your SELECT statement to make it easier to
read. I've reformatted it below using one such formatting standard that
I've used in the past, but you can of course choose your own. The
important thing is that it isn't simply one large blob of text.

Secondly, use table aliases. After the table name in the FROM clause,
you can include a table alias, which you can use elsewhere (including in
the SELECT clause) to refer to the table. These are often much shorter
than the table names, making the whole statement easier to read. Also,
if you are including a table more than once (for different join
conditions), I think you are required to have aliases to distinguish
between the two table uses. You are actually doing this in your
statement, and it gives rise to an ambiguity.

Thirdly, JOINs are complicated, as there are many options: INNER
JOINs, LEFT, RIGHT and FULL OUTER JOINs, CROSS JOINs, NATURAL JOINs,
etc.

https://en.wikipedia.org//wiki/Join_(SQL)

The most common (in my experience) are INNER and LEFT OUTER JOINs.
Don't worry about the rest for now.

Think of it this way:

For inner joins, with the condition in the FROM clause

(i.e. FROM tableA a INNER JOIN tableB b on a.id = b.id)

You are adding all rows from tableA to a result set, then, for each row
in tableB that matches the condition, you are adding all the fields
from tableB to that row of the result set (if more than one row matches
a row in the result set, the existing row is duplicated). If a row in
the result set doesn't match any rows in tableB, it is removed from the
result set.

For OUTER JOINS, of the form:

FROM tableA a LEFT OUTER JOIN tableB b on a.id = b.id

You are doing the same thing, except that should a row in the result
set not match any rows in tableB, it is not discarded from the result
set, and instead NULL values are used for all fields that would
otherwise have come from tableB.


Now your statement has a lot of AND parts in the JOINs, which don't
have proper conditions, and so they look like they may have come about
due to you not understanding the syntax properly, and aren't actually
needed, so I have removed them.

I've also re-ordered the FROM list, which shouldn't strictly speaking
be necessary (I think), but does make it easier to follow logically if
tables are listed in the FROM list before other tables reference them
in their JOIN conditions.

You're also missing the "tCntEntityPerson" table in the FROM list, as
it is used in the JOIN conditions of other tables, but as you've listed
"tCntEntity" twice, with the second one having "tCntEntityPerson" in
the join condition, I've assumed that this was a mistype (or
misunderstanding), and I've corrected that to be the missing
"tCntEntityPerson" in the FROM list.

The same with "tCntContactAddress".

And as you've included the "tCntPerson" table twice, joined to
different tables, there is an ambiguity in your SELECT clause as to
which table you are referring to. I've used aliases to clarify that,
but you'll have to correct those two lines in the SEELECT statement
yourself, as only you know which table you want data from.

So, your SELECT statement should be *something* like the following:


SELECT
    core_cat."category",
    ent."entity_name",
    pers_from_[ent or addr?]."first_name",
    pers_from_[ent or addr?]."last_name",
    addr."location_name",
    addr."address1"
FROM
    "tCntEntityCategory" ent_cat
    JOIN "tCntEntity" ent
        ON ent_cat."entity_id" = ent."entity_id"
    JOIN "tCoreCategory" core_cat
        ON ent_cat."category_id" = core_cat."category_id"
        AND core_cat."category" LIKE 'Internal -%';
    JOIN "tCntEntityPerson" ent_pers
        ON ent_pers."entity_id" = ent."entity_id"
    JOIN "tCntPerson" pers_from_ent
        ON ent_pers."person_id" = pers_from_ent."person_id"
    LEFT OUTER JOIN "tCntContactAddress" ctct_addr
        ON ctct_addr."entity_id" = ent."entity_id"
    LEFT OUTER JOIN "tCntPerson" pers_from_addr
        ON ctct_addr."person_id" = pers_from_addr."person_id"
    LEFT OUTER JOIN "tCntAddress" addr
        ON ctct_addr."address_id" = addr."address_id"



(Sorry, I haven't actually tested this, just eyeballed it, so this may
be syntactically or logically incorrect, but it should get you pretty
close to what you need.)

Hope this helps.


Paul


On Fri, 1 Jan 2016 12:06:56 -0500
Don Parris <parrisdc@gmail.com> wrote:

Update:  I did try re-writing the query with LEFT/RIGHT JOINS, but
all I get are syntax errors.  Maybe I have my SQL statement incorrect?

SELECT "tCoreCategory"."category", "tCntEntity"."entity_name",
"tCntPerson"."first_name", "tCntPerson"."last_name",
"tCntAddress"."location_name", "tCntAddress"."address1"
FROM "tCntEntityCategory" JOIN "tCntEntity" ON
"tCntEntityCategory"."entity_id" = "tCntEntity"."entity_id" AND
"tCntEntityCategory" JOIN "tCoreCategory" ON
"tCntEntityCategory"."category_id" = "tCoreCategory"."category_id" AND
"tCntEntityPerson" JOIN "tCntEntity" ON
"tCntEntityPerson"."entity_id" = "tCntEntity"."entity_id" AND
"tCntEntityPerson" JOIN "tCntPerson" ON
"tCntEntityPerson"."person_id" = "tCntPerson"."person_id" AND
"tCntContactAddress" LEFT JOIN "tCntEntity" ON
"tCntContactAddress"."entity_id" = "tCntEntity"."entity_id" AND
"tCntContactAddress" LEFT JOIN "tCntPerson" ON
"tCntContactAddress"."person_id" = "tCntPerson"."person_id" AND
"tCntContactAddress" LEFT JOIN "tCntAddress" ON
"tCntContactAddress"."address_id" = "tCntAddress"."address_id" AND
"tCoreCategory"."category" LIKE 'Internal -%';



On Fri, Jan 1, 2016 at 7:08 AM, Don Parris <parrisdc@gmail.com> wrote:

Hi all,

I have a set of tables for contacts, and a somewhat complex query
that seeks all the available contact information on a subset of the
contacts. By "incomplete result set", I mean I have one contact
that does not show up in the query results, but should.

I know why: that contact has phone and e-mail information, but does
not yet have a record in the address table.  Everyone else who has
an address record in the address table shows up in the results.  I
would like to see what information *is* available (regardless of
whether or not there is an address record (or even if there is an
address, but no phone/email information).

I am fairly sure I need to change the join type (using LEFT or
RIGHT) on the relevant table(s), just not sure how exactly.  My
current query is (built in Design View, copied from SQL View):

SELECT "tCntPerson"."first_name" "First Name",
"tCntPerson"."last_name" "Last Name", "tCoreCategory"."category"
"Category", "tCntEntity"."entity_name" "Entity",
"tCntAddressType"."address_type" "Addr Type",
"tCntAddress"."location_name" "Location", "tCntAddress"."address1"
"Address", "tCntAddress"."locality" "Locality",
"tCntRegion"."region_postal" "Region", "tCntAddress"."postcode"
"PostCode", "tCntCountry"."country_un" "Country",
"tCntContactInfo"."priority" "Cnt Priority",
"tCntContactMethod"."contact_method" "Method",
"tCntContactInfo"."contact_info" FROM "tCntEntityCategory",
"tCntEntity", "tCntEntityPerson", "tCntPerson", "tCoreCategory",
"tCoreType", "tCntContactAddress", "tCntAddress", "tCntRegion",
"tCntCountry", "tCntContactInfo", "tCntContactMethod",
"tCntPersonContactInfo", "tCntAddressType" WHERE
"tCntEntityCategory"."entity_id" = "tCntEntity"."entity_id" AND
"tCntEntityPerson"."entity_id" = "tCntEntity"."entity_id" AND
"tCntEntityPerson"."person_id" = "tCntPerson"."person_id" AND
"tCntEntityCategory"."category_id" = "tCoreCategory"."category_id"
AND "tCoreCategory"."type_id" = "tCoreType"."type_id" AND
"tCntContactAddress"."entity_id" = "tCntEntity"."entity_id" AND
"tCntContactAddress"."person_id" = "tCntPerson"."person_id" AND
"tCntContactAddress"."address_id" = "tCntAddress"."address_id" AND
"tCntAddress"."region_id" = "tCntRegion"."region_id" AND
"tCntAddress"."country_id" = "tCntCountry"."country_id" AND
"tCntContactInfo"."contact_method_id" =
"tCntContactMethod"."contact_method_id" AND
"tCntPersonContactInfo"."contact_info_id" =
"tCntContactInfo"."contact_info_id" AND
"tCntPersonContactInfo"."person_id" = "tCntPerson"."person_id" AND
"tCntAddress"."address_type_id" =
"tCntAddressType"."address_type_id" AND "tCoreCategory"."category"
LIKE 'Internal -%' ORDER BY "Last Name" ASC, "Entity" ASC, "Cnt
Priority" ASC

The most relevant tables (for this query) are:
<> tCntEntity (Business or last name)
<> tCntPerson (a person can be associated with many
entities/addresses) <> tCntAddress
<> tCntContactAddress (links the corresponding entity and person
with a specific address)

Quick example (that I hope helps with understanding the design
logic): John Jones belongs to an entity called "Jones" that has a
home address. He also belongs to an entity called "Widget Corp"
that has a business address.  My query should pull up Mr Jones
regardless of whether there is an address record affiliated with
the "Jones" entity.

 





-- 
To unsubscribe e-mail to: users+unsubscribe@global.libreoffice.org
Problems? http://www.libreoffice.org/get-help/mailing-lists/how-to-unsubscribe/
Posting guidelines + more: http://wiki.documentfoundation.org/Netiquette
List archive: http://listarchives.libreoffice.org/global/users/
All messages sent to this list will be publicly archived and cannot be deleted

Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.