Revision 4739
Added by Aaron Marcuse-Kubitza over 12 years ago
schemas/vegbien.my.sql | ||
---|---|---|
640 | 640 |
|
641 | 641 |
|
642 | 642 |
-- |
643 |
-- Name: place; Type: TABLE; Schema: public; Owner: -; Tablespace: |
|
643 |
-- Name: placepath; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
|
644 | 644 |
-- |
645 | 645 |
|
646 |
CREATE TABLE place ( |
|
647 |
place_id int(11) NOT NULL, |
|
648 |
parent_id int(11), |
|
649 |
rank text NOT NULL, |
|
650 |
placename text NOT NULL, |
|
646 |
CREATE TABLE placepath ( |
|
647 |
placepath_id int(11) NOT NULL, |
|
648 |
datasource_id int(11) NOT NULL, |
|
651 | 649 |
placecode text, |
652 |
placedescription text, |
|
653 |
accessioncode text |
|
650 |
place_id int(11), |
|
651 |
continent text, |
|
652 |
country text, |
|
653 |
stateprovince text, |
|
654 |
county text, |
|
655 |
municipality text, |
|
656 |
site text |
|
654 | 657 |
); |
655 | 658 |
|
656 | 659 |
|
657 | 660 |
-- |
658 |
-- Name: TABLE place; Type: COMMENT; Schema: public; Owner: - |
|
661 |
-- Name: TABLE placepath; Type: COMMENT; Schema: public; Owner: -
|
|
659 | 662 |
-- |
660 | 663 |
|
661 | 664 |
|
662 | 665 |
|
663 | 666 |
|
664 | 667 |
-- |
665 |
-- Name: place_ancestor; Type: TABLE; Schema: public; Owner: -; Tablespace: |
|
666 |
-- |
|
667 |
|
|
668 |
CREATE TABLE place_ancestor ( |
|
669 |
place_id int(11) NOT NULL, |
|
670 |
ancestor_id int(11) NOT NULL |
|
671 |
); |
|
672 |
|
|
673 |
|
|
674 |
-- |
|
675 | 668 |
-- Name: plantobservation; Type: TABLE; Schema: public; Owner: -; Tablespace: |
676 | 669 |
-- |
677 | 670 |
|
... | ... | |
869 | 862 |
-- |
870 | 863 |
|
871 | 864 |
CREATE VIEW analytical_db_view AS |
872 |
SELECT datasource.organizationname AS `dataSourceName`, taxonpath.family, taxonpath.genus, taxonpath.species, COALESCE(taxonpath.scientificnamewithauthor, taxonpath.scientificname) AS taxon, taxonpath.scientificnameauthor AS `taxonAuthor`, taxonpath.variety AS `taxonMorphospecies`, country.placename AS country, stateprovince.placename AS `stateProvince`, county.placename AS `countyParish`, taxonoccurrence.verbatimcollectorname AS collector, plantobservation.collectionnumber AS `collectionNumber`, array_to_string(ARRAY[identifiedby.givenname, identifiedby.middlename, identifiedby.surname], CAST(' ' AS text)) AS `identifiedBy`, aggregateoccurrence.collectiondate AS `observationDate`, location.authorlocationcode AS `plotCode`, location.area AS `plotAreaHa`, method.name AS `plotMethod`, locationcoords.latitude, locationcoords.longitude, location.elevation AS elevation_m, taxonoccurrence.iscultivated AS `isCultivated`, taxonoccurrence.cultivatedbasis AS `isCultivatedReason`, aggregateoccurrence.cover AS `pctCover` FROM ((((((((((((((((((((location JOIN party datasource ON (((datasource.party_id = location.datasource_id) AND (datasource.organizationname IS NOT NULL)))) LEFT JOIN locationcoords USING (location_id)) LEFT JOIN locationplace USING (location_id)) LEFT JOIN place_ancestor continent_ancestor ON ((continent_ancestor.place_id = locationplace.placepath_id))) LEFT JOIN place continent ON (((continent.place_id = continent_ancestor.ancestor_id) AND (continent.rank = CAST('continent' AS placerank))))) LEFT JOIN place_ancestor country_ancestor ON ((country_ancestor.place_id = locationplace.placepath_id))) LEFT JOIN place country ON (((country.place_id = country_ancestor.ancestor_id) AND (country.rank = CAST('country' AS placerank))))) LEFT JOIN place_ancestor stateprovince_ancestor ON ((stateprovince_ancestor.place_id = locationplace.placepath_id))) LEFT JOIN place stateprovince ON (((stateprovince.place_id = stateprovince_ancestor.ancestor_id) AND (stateprovince.rank = CAST('stateProvince' AS placerank))))) LEFT JOIN place_ancestor county_ancestor ON ((county_ancestor.place_id = locationplace.placepath_id))) LEFT JOIN place county ON (((county.place_id = county_ancestor.ancestor_id) AND (county.rank = CAST('county' AS placerank))))) JOIN locationevent USING (location_id)) LEFT JOIN method USING (method_id)) JOIN taxonoccurrence USING (locationevent_id)) JOIN taxondetermination USING (taxonoccurrence_id)) LEFT JOIN party identifiedby ON ((identifiedby.party_id = taxondetermination.party_id))) JOIN taxonpath USING (taxonpath_id)) LEFT JOIN aggregateoccurrence USING (taxonoccurrence_id)) LEFT JOIN plantobservation USING (aggregateoccurrence_id)) LEFT JOIN specimenreplicate USING (plantobservation_id));
|
|
865 |
SELECT datasource.organizationname AS `dataSourceName`, taxonpath.family, taxonpath.genus, taxonpath.species, COALESCE(taxonpath.scientificnamewithauthor, taxonpath.scientificname) AS taxon, taxonpath.scientificnameauthor AS `taxonAuthor`, taxonpath.variety AS `taxonMorphospecies`, placepath.country, placepath.stateprovince AS `stateProvince`, placepath.county AS `countyParish`, taxonoccurrence.verbatimcollectorname AS collector, plantobservation.collectionnumber AS `collectionNumber`, array_to_string(ARRAY[identifiedby.givenname, identifiedby.middlename, identifiedby.surname], CAST(' ' AS text)) AS `identifiedBy`, aggregateoccurrence.collectiondate AS `observationDate`, location.authorlocationcode AS `plotCode`, location.area AS `plotAreaHa`, method.name AS `plotMethod`, locationcoords.latitude, locationcoords.longitude, location.elevation AS elevation_m, taxonoccurrence.iscultivated AS `isCultivated`, taxonoccurrence.cultivatedbasis AS `isCultivatedReason`, aggregateoccurrence.cover AS `pctCover` FROM (((((((((((((location JOIN party datasource ON (((datasource.party_id = location.datasource_id) AND (datasource.organizationname IS NOT NULL)))) LEFT JOIN locationcoords USING (location_id)) LEFT JOIN locationplace USING (location_id)) LEFT JOIN placepath USING (placepath_id)) JOIN locationevent USING (location_id)) LEFT JOIN method USING (method_id)) JOIN taxonoccurrence USING (locationevent_id)) JOIN taxondetermination USING (taxonoccurrence_id)) LEFT JOIN party identifiedby ON ((identifiedby.party_id = taxondetermination.party_id))) JOIN taxonpath USING (taxonpath_id)) LEFT JOIN aggregateoccurrence USING (taxonoccurrence_id)) LEFT JOIN plantobservation USING (aggregateoccurrence_id)) LEFT JOIN specimenreplicate USING (plantobservation_id));
|
|
873 | 866 |
|
874 | 867 |
|
875 | 868 |
-- |
876 |
-- Name: VIEW analytical_db_view; Type: COMMENT; Schema: public; Owner: - |
|
877 |
-- |
|
878 |
|
|
879 |
|
|
880 |
|
|
881 |
|
|
882 |
-- |
|
883 | 869 |
-- Name: classcontributor; Type: TABLE; Schema: public; Owner: -; Tablespace: |
884 | 870 |
-- |
885 | 871 |
|
... | ... | |
1567 | 1553 |
|
1568 | 1554 |
|
1569 | 1555 |
-- |
1570 |
-- Name: place_place_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
|
1556 |
-- Name: place; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
|
1571 | 1557 |
-- |
1572 | 1558 |
|
1559 |
CREATE TABLE place ( |
|
1560 |
place_id int(11) NOT NULL, |
|
1561 |
parent_id int(11), |
|
1562 |
rank text NOT NULL, |
|
1563 |
placename text NOT NULL, |
|
1564 |
placecode text, |
|
1565 |
placedescription text, |
|
1566 |
accessioncode text |
|
1567 |
); |
|
1573 | 1568 |
|
1574 | 1569 |
|
1575 |
|
|
1576 | 1570 |
-- |
1577 |
-- Name: place_place_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
|
1571 |
-- Name: TABLE place; Type: COMMENT; Schema: public; Owner: -
|
|
1578 | 1572 |
-- |
1579 | 1573 |
|
1580 | 1574 |
|
1581 | 1575 |
|
1582 | 1576 |
|
1583 | 1577 |
-- |
1584 |
-- Name: placecorrelation; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
|
1578 |
-- Name: place_ancestor; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
|
1585 | 1579 |
-- |
1586 | 1580 |
|
1587 |
CREATE TABLE placecorrelation ( |
|
1588 |
placecorrelation_id int(11) NOT NULL, |
|
1589 |
parentplace_id int(11) NOT NULL, |
|
1590 |
childplace_id int(11) NOT NULL, |
|
1591 |
placeconvergence text NOT NULL |
|
1581 |
CREATE TABLE place_ancestor ( |
|
1582 |
place_id int(11) NOT NULL, |
|
1583 |
ancestor_id int(11) NOT NULL |
|
1592 | 1584 |
); |
1593 | 1585 |
|
1594 | 1586 |
|
1595 | 1587 |
-- |
1596 |
-- Name: placecorrelation_placecorrelation_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
|
1588 |
-- Name: place_place_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
|
1597 | 1589 |
-- |
1598 | 1590 |
|
1599 | 1591 |
|
1600 | 1592 |
|
1601 | 1593 |
|
1602 | 1594 |
-- |
1603 |
-- Name: placecorrelation_placecorrelation_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
|
1595 |
-- Name: place_place_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
|
1604 | 1596 |
-- |
1605 | 1597 |
|
1606 | 1598 |
|
1607 | 1599 |
|
1608 | 1600 |
|
1609 | 1601 |
-- |
1610 |
-- Name: placepath; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
|
1602 |
-- Name: placecorrelation; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
|
1611 | 1603 |
-- |
1612 | 1604 |
|
1613 |
CREATE TABLE placepath ( |
|
1614 |
placepath_id int(11) NOT NULL, |
|
1615 |
datasource_id int(11) NOT NULL, |
|
1616 |
placecode text, |
|
1617 |
place_id int(11), |
|
1618 |
continent text, |
|
1619 |
country text, |
|
1620 |
stateprovince text, |
|
1621 |
county text, |
|
1622 |
municipality text, |
|
1623 |
site text |
|
1605 |
CREATE TABLE placecorrelation ( |
|
1606 |
placecorrelation_id int(11) NOT NULL, |
|
1607 |
parentplace_id int(11) NOT NULL, |
|
1608 |
childplace_id int(11) NOT NULL, |
|
1609 |
placeconvergence text NOT NULL |
|
1624 | 1610 |
); |
1625 | 1611 |
|
1626 | 1612 |
|
1627 | 1613 |
-- |
1628 |
-- Name: TABLE placepath; Type: COMMENT; Schema: public; Owner: -
|
|
1614 |
-- Name: placecorrelation_placecorrelation_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
|
1629 | 1615 |
-- |
1630 | 1616 |
|
1631 | 1617 |
|
1632 | 1618 |
|
1633 | 1619 |
|
1634 | 1620 |
-- |
1621 |
-- Name: placecorrelation_placecorrelation_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - |
|
1622 |
-- |
|
1623 |
|
|
1624 |
|
|
1625 |
|
|
1626 |
|
|
1627 |
-- |
|
1635 | 1628 |
-- Name: placepath_placepath_id_seq; Type: SEQUENCE; Schema: public; Owner: - |
1636 | 1629 |
-- |
1637 | 1630 |
|
schemas/vegbien.sql | ||
---|---|---|
919 | 919 |
|
920 | 920 |
|
921 | 921 |
-- |
922 |
-- Name: place; Type: TABLE; Schema: public; Owner: -; Tablespace: |
|
922 |
-- Name: placepath; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
|
923 | 923 |
-- |
924 | 924 |
|
925 |
CREATE TABLE place ( |
|
926 |
place_id integer NOT NULL, |
|
927 |
parent_id integer, |
|
928 |
rank placerank NOT NULL, |
|
929 |
placename text NOT NULL, |
|
925 |
CREATE TABLE placepath ( |
|
926 |
placepath_id integer NOT NULL, |
|
927 |
datasource_id integer NOT NULL, |
|
930 | 928 |
placecode text, |
931 |
placedescription text, |
|
932 |
accessioncode text |
|
929 |
place_id integer, |
|
930 |
continent text, |
|
931 |
country text, |
|
932 |
stateprovince text, |
|
933 |
county text, |
|
934 |
municipality text, |
|
935 |
site text |
|
933 | 936 |
); |
934 | 937 |
|
935 | 938 |
|
936 | 939 |
-- |
937 |
-- Name: TABLE place; Type: COMMENT; Schema: public; Owner: - |
|
940 |
-- Name: TABLE placepath; Type: COMMENT; Schema: public; Owner: -
|
|
938 | 941 |
-- |
939 | 942 |
|
940 |
COMMENT ON TABLE place IS 'VegBank''s namedPlace table.';
|
|
943 |
COMMENT ON TABLE placepath IS 'To include a place at a rank with no explicit column, create a place for it and point to it using place_id. To include multiple such places, chain the places together using parent_id, as a form of ordered linked list. Note that lower-level places should point to higher-level places.';
|
|
941 | 944 |
|
942 | 945 |
|
943 | 946 |
-- |
944 |
-- Name: place_ancestor; Type: TABLE; Schema: public; Owner: -; Tablespace: |
|
945 |
-- |
|
946 |
|
|
947 |
CREATE TABLE place_ancestor ( |
|
948 |
place_id integer NOT NULL, |
|
949 |
ancestor_id integer NOT NULL |
|
950 |
); |
|
951 |
|
|
952 |
|
|
953 |
-- |
|
954 | 947 |
-- Name: plantobservation; Type: TABLE; Schema: public; Owner: -; Tablespace: |
955 | 948 |
-- |
956 | 949 |
|
... | ... | |
1149 | 1142 |
-- |
1150 | 1143 |
|
1151 | 1144 |
CREATE VIEW analytical_db_view AS |
1152 |
SELECT datasource.organizationname AS "dataSourceName", taxonpath.family, taxonpath.genus, taxonpath.species, COALESCE(taxonpath.scientificnamewithauthor, taxonpath.scientificname) AS taxon, taxonpath.scientificnameauthor AS "taxonAuthor", taxonpath.variety AS "taxonMorphospecies", country.placename AS country, stateprovince.placename AS "stateProvince", county.placename AS "countyParish", taxonoccurrence.verbatimcollectorname AS collector, plantobservation.collectionnumber AS "collectionNumber", array_to_string(ARRAY[identifiedby.givenname, identifiedby.middlename, identifiedby.surname], ' '::text) AS "identifiedBy", aggregateoccurrence.collectiondate AS "observationDate", location.authorlocationcode AS "plotCode", location.area AS "plotAreaHa", method.name AS "plotMethod", locationcoords.latitude, locationcoords.longitude, location.elevation AS elevation_m, taxonoccurrence.iscultivated AS "isCultivated", taxonoccurrence.cultivatedbasis AS "isCultivatedReason", aggregateoccurrence.cover AS "pctCover" FROM ((((((((((((((((((((location JOIN party datasource ON (((datasource.party_id = location.datasource_id) AND (datasource.organizationname IS NOT NULL)))) LEFT JOIN locationcoords USING (location_id)) LEFT JOIN locationplace USING (location_id)) LEFT JOIN place_ancestor continent_ancestor ON ((continent_ancestor.place_id = locationplace.placepath_id))) LEFT JOIN place continent ON (((continent.place_id = continent_ancestor.ancestor_id) AND (continent.rank = 'continent'::placerank)))) LEFT JOIN place_ancestor country_ancestor ON ((country_ancestor.place_id = locationplace.placepath_id))) LEFT JOIN place country ON (((country.place_id = country_ancestor.ancestor_id) AND (country.rank = 'country'::placerank)))) LEFT JOIN place_ancestor stateprovince_ancestor ON ((stateprovince_ancestor.place_id = locationplace.placepath_id))) LEFT JOIN place stateprovince ON (((stateprovince.place_id = stateprovince_ancestor.ancestor_id) AND (stateprovince.rank = 'stateProvince'::placerank)))) LEFT JOIN place_ancestor county_ancestor ON ((county_ancestor.place_id = locationplace.placepath_id))) LEFT JOIN place county ON (((county.place_id = county_ancestor.ancestor_id) AND (county.rank = 'county'::placerank)))) JOIN locationevent USING (location_id)) LEFT JOIN method USING (method_id)) JOIN taxonoccurrence USING (locationevent_id)) JOIN taxondetermination USING (taxonoccurrence_id)) LEFT JOIN party identifiedby ON ((identifiedby.party_id = taxondetermination.party_id))) JOIN taxonpath USING (taxonpath_id)) LEFT JOIN aggregateoccurrence USING (taxonoccurrence_id)) LEFT JOIN plantobservation USING (aggregateoccurrence_id)) LEFT JOIN specimenreplicate USING (plantobservation_id));
|
|
1145 |
SELECT datasource.organizationname AS "dataSourceName", taxonpath.family, taxonpath.genus, taxonpath.species, COALESCE(taxonpath.scientificnamewithauthor, taxonpath.scientificname) AS taxon, taxonpath.scientificnameauthor AS "taxonAuthor", taxonpath.variety AS "taxonMorphospecies", placepath.country, placepath.stateprovince AS "stateProvince", placepath.county AS "countyParish", taxonoccurrence.verbatimcollectorname AS collector, plantobservation.collectionnumber AS "collectionNumber", array_to_string(ARRAY[identifiedby.givenname, identifiedby.middlename, identifiedby.surname], ' '::text) AS "identifiedBy", aggregateoccurrence.collectiondate AS "observationDate", location.authorlocationcode AS "plotCode", location.area AS "plotAreaHa", method.name AS "plotMethod", locationcoords.latitude, locationcoords.longitude, location.elevation AS elevation_m, taxonoccurrence.iscultivated AS "isCultivated", taxonoccurrence.cultivatedbasis AS "isCultivatedReason", aggregateoccurrence.cover AS "pctCover" FROM (((((((((((((location JOIN party datasource ON (((datasource.party_id = location.datasource_id) AND (datasource.organizationname IS NOT NULL)))) LEFT JOIN locationcoords USING (location_id)) LEFT JOIN locationplace USING (location_id)) LEFT JOIN placepath USING (placepath_id)) JOIN locationevent USING (location_id)) LEFT JOIN method USING (method_id)) JOIN taxonoccurrence USING (locationevent_id)) JOIN taxondetermination USING (taxonoccurrence_id)) LEFT JOIN party identifiedby ON ((identifiedby.party_id = taxondetermination.party_id))) JOIN taxonpath USING (taxonpath_id)) LEFT JOIN aggregateoccurrence USING (taxonoccurrence_id)) LEFT JOIN plantobservation USING (aggregateoccurrence_id)) LEFT JOIN specimenreplicate USING (plantobservation_id));
|
|
1153 | 1146 |
|
1154 | 1147 |
|
1155 | 1148 |
-- |
1156 |
-- Name: VIEW analytical_db_view; Type: COMMENT; Schema: public; Owner: - |
|
1157 |
-- |
|
1158 |
|
|
1159 |
COMMENT ON VIEW analytical_db_view IS 'To generate hierarchical-table joins: |
|
1160 |
|
|
1161 |
place: |
|
1162 |
For each placerank value, replace regexp ".*" with: |
|
1163 |
----- |
|
1164 |
LEFT JOIN place_ancestor AS $0_ancestor |
|
1165 |
ON $0_ancestor.place_id = locationcoords.place_id |
|
1166 |
LEFT JOIN place AS $0 |
|
1167 |
ON $0.place_id = $0_ancestor.ancestor_id |
|
1168 |
AND $0.rank = ''$0'' |
|
1169 |
----- |
|
1170 |
'; |
|
1171 |
|
|
1172 |
|
|
1173 |
-- |
|
1174 | 1149 |
-- Name: classcontributor; Type: TABLE; Schema: public; Owner: -; Tablespace: |
1175 | 1150 |
-- |
1176 | 1151 |
|
... | ... | |
1994 | 1969 |
|
1995 | 1970 |
|
1996 | 1971 |
-- |
1972 |
-- Name: place; Type: TABLE; Schema: public; Owner: -; Tablespace: |
|
1973 |
-- |
|
1974 |
|
|
1975 |
CREATE TABLE place ( |
|
1976 |
place_id integer NOT NULL, |
|
1977 |
parent_id integer, |
|
1978 |
rank placerank NOT NULL, |
|
1979 |
placename text NOT NULL, |
|
1980 |
placecode text, |
|
1981 |
placedescription text, |
|
1982 |
accessioncode text |
|
1983 |
); |
|
1984 |
|
|
1985 |
|
|
1986 |
-- |
|
1987 |
-- Name: TABLE place; Type: COMMENT; Schema: public; Owner: - |
|
1988 |
-- |
|
1989 |
|
|
1990 |
COMMENT ON TABLE place IS 'VegBank''s namedPlace table.'; |
|
1991 |
|
|
1992 |
|
|
1993 |
-- |
|
1994 |
-- Name: place_ancestor; Type: TABLE; Schema: public; Owner: -; Tablespace: |
|
1995 |
-- |
|
1996 |
|
|
1997 |
CREATE TABLE place_ancestor ( |
|
1998 |
place_id integer NOT NULL, |
|
1999 |
ancestor_id integer NOT NULL |
|
2000 |
); |
|
2001 |
|
|
2002 |
|
|
2003 |
-- |
|
1997 | 2004 |
-- Name: place_place_id_seq; Type: SEQUENCE; Schema: public; Owner: - |
1998 | 2005 |
-- |
1999 | 2006 |
|
... | ... | |
2044 | 2051 |
|
2045 | 2052 |
|
2046 | 2053 |
-- |
2047 |
-- Name: placepath; Type: TABLE; Schema: public; Owner: -; Tablespace: |
|
2048 |
-- |
|
2049 |
|
|
2050 |
CREATE TABLE placepath ( |
|
2051 |
placepath_id integer NOT NULL, |
|
2052 |
datasource_id integer NOT NULL, |
|
2053 |
placecode text, |
|
2054 |
place_id integer, |
|
2055 |
continent text, |
|
2056 |
country text, |
|
2057 |
stateprovince text, |
|
2058 |
county text, |
|
2059 |
municipality text, |
|
2060 |
site text |
|
2061 |
); |
|
2062 |
|
|
2063 |
|
|
2064 |
-- |
|
2065 |
-- Name: TABLE placepath; Type: COMMENT; Schema: public; Owner: - |
|
2066 |
-- |
|
2067 |
|
|
2068 |
COMMENT ON TABLE placepath IS 'To include a place at a rank with no explicit column, create a place for it and point to it using place_id. To include multiple such places, chain the places together using parent_id, as a form of ordered linked list. Note that lower-level places should point to higher-level places.'; |
|
2069 |
|
|
2070 |
|
|
2071 |
-- |
|
2072 | 2054 |
-- Name: placepath_placepath_id_seq; Type: SEQUENCE; Schema: public; Owner: - |
2073 | 2055 |
-- |
2074 | 2056 |
|
Also available in: Unified diff
schemas/vegbien.sql: analytical_db_view: Use new denormalized placepath table instead of place, which significantly reduces the number of joins