⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 query.sgml

📁 PostgreSQL7.4.6 for Linux
💻 SGML
📖 第 1 页 / 共 2 页
字号:
       because there is no matching entry in the       <classname>cities</classname> table for Hayward, so the join       ignores the unmatched rows in the weather table.  We will see       shortly how this can be fixed.      </para>     </listitem>     <listitem>      <para>       There are two columns containing the city name.  This is       correct because the lists of columns of the       <classname>weather</classname> and the       <classname>cities</classname> table are concatenated.  In       practice this is undesirable, though, so you will probably want       to list the output columns explicitly rather than using       <literal>*</literal>:<programlisting>SELECT city, temp_lo, temp_hi, prcp, date, location    FROM weather, cities    WHERE city = name;</programlisting>      </para>     </listitem>    </itemizedlist>   </para>   <formalpara>    <title>Exercise:</title>    <para>     Attempt to find out the semantics of this query when the     <literal>WHERE</literal> clause is omitted.    </para>   </formalpara>   <para>    Since the columns all had different names, the parser    automatically found out which table they belong to, but it is good    style to fully qualify column names in join queries:<programlisting>SELECT weather.city, weather.temp_lo, weather.temp_hi,       weather.prcp, weather.date, cities.location    FROM weather, cities    WHERE cities.name = weather.city;</programlisting>   </para>   <para>    Join queries of the kind seen thus far can also be written in this    alternative form:<programlisting>SELECT *    FROM weather INNER JOIN cities ON (weather.city = cities.name);</programlisting>    This syntax is not as commonly used as the one above, but we show    it here to help you understand the following topics.   </para>   <para>    <indexterm><primary>join</primary><secondary>outer</secondary></indexterm>    Now we will figure out how we can get the Hayward records back in.    What we want the query to do is to scan the    <classname>weather</classname> table and for each row to find the    matching <classname>cities</classname> row.  If no matching row is    found we want some <quote>empty values</quote> to be substituted    for the <classname>cities</classname> table's columns.  This kind    of query is called an <firstterm>outer join</firstterm>.  (The    joins we have seen so far are inner joins.)  The command looks    like this:<programlisting>SELECT *    FROM weather LEFT OUTER JOIN cities ON (weather.city = cities.name);     city      | temp_lo | temp_hi | prcp |    date    |     name      | location---------------+---------+---------+------+------------+---------------+----------- Hayward       |      37 |      54 |      | 1994-11-29 |               | San Francisco |      46 |      50 | 0.25 | 1994-11-27 | San Francisco | (-194,53) San Francisco |      43 |      57 |    0 | 1994-11-29 | San Francisco | (-194,53)(3 rows)</programlisting>    This query is called a <firstterm>left outer    join</firstterm> because the table mentioned on the left of the    join operator will have each of its rows in the output at least    once, whereas the table on the right will only have those rows    output that match some row of the left table.  When outputting a    left-table row for which there is no right-table match, empty (null)    values are substituted for the right-table columns.   </para>   <formalpara>    <title>Exercise:</title>    <para>     There are also right outer joins and full outer joins.  Try to     find out what those do.    </para>   </formalpara>   <para>    <indexterm><primary>join</primary><secondary>self</secondary></indexterm>    <indexterm><primary>alias</primary><secondary>for table name in query</secondary></indexterm>    We can also join a table against itself.  This is called a    <firstterm>self join</firstterm>.  As an example, suppose we wish    to find all the weather records that are in the temperature range    of other weather records.  So we need to compare the    <structfield>temp_lo</> and <structfield>temp_hi</> columns of    each <classname>weather</classname> row to the    <structfield>temp_lo</structfield> and    <structfield>temp_hi</structfield> columns of all other    <classname>weather</classname> rows.  We can do this with the    following query:<programlisting>SELECT W1.city, W1.temp_lo AS low, W1.temp_hi AS high,    W2.city, W2.temp_lo AS low, W2.temp_hi AS high    FROM weather W1, weather W2    WHERE W1.temp_lo < W2.temp_lo    AND W1.temp_hi > W2.temp_hi;     city      | low | high |     city      | low | high---------------+-----+------+---------------+-----+------ San Francisco |  43 |   57 | San Francisco |  46 |   50 Hayward       |  37 |   54 | San Francisco |  46 |   50(2 rows)</programlisting>         Here we have relabeled the weather table as <literal>W1</> and    <literal>W2</> to be able to distinguish the left and right side    of the join.  You can also use these kinds of aliases in other    queries to save some typing, e.g.:<programlisting>SELECT *    FROM weather w, cities c    WHERE w.city = c.name;</programlisting>    You will encounter this style of abbreviating quite frequently.   </para>  </sect1>  <sect1 id="tutorial-agg">   <title>Aggregate Functions</title>   <indexterm zone="tutorial-agg">    <primary>aggregate function</primary>   </indexterm>   <para>    <indexterm><primary>average</primary></indexterm>    <indexterm><primary>count</primary></indexterm>    <indexterm><primary>max</primary></indexterm>    <indexterm><primary>min</primary></indexterm>    <indexterm><primary>sum</primary></indexterm>    Like  most  other relational database products,     <productname>PostgreSQL</productname> supports    aggregate functions.    An aggregate function computes a single result from multiple input rows.    For example, there are aggregates to compute the    <function>count</function>, <function>sum</function>,    <function>avg</function> (average), <function>max</function> (maximum) and    <function>min</function> (minimum) over a set of rows.   </para>   <para>    As an example, we can find the highest low-temperature reading anywhere    with<programlisting>SELECT max(temp_lo) FROM weather;</programlisting><screen> max-----  46(1 row)</screen>   </para>   <para>    <indexterm><primary>subquery</primary></indexterm>    If we wanted to know what city (or cities) that reading occurred in,    we might try<programlisting>SELECT city FROM weather WHERE temp_lo = max(temp_lo);     <lineannotation>WRONG</lineannotation></programlisting>    but this will not work since the aggregate    <function>max</function> cannot be used in the    <literal>WHERE</literal> clause.  (This restriction exists because    the <literal>WHERE</literal> clause determines the rows that will    go into the aggregation stage; so it has to be evaluated before    aggregate functions are computed.)    However, as is often the case    the query can be restated to accomplish the intended result, here    by using a <firstterm>subquery</firstterm>:<programlisting>SELECT city FROM weather    WHERE temp_lo = (SELECT max(temp_lo) FROM weather);</programlisting><screen>     city--------------- San Francisco(1 row)</screen>    This is OK because the subquery is an independent computation    that computes its own aggregate separately from what is happening    in the outer query.   </para>   <para>    <indexterm><primary>GROUP BY</primary></indexterm>    <indexterm><primary>HAVING</primary></indexterm>    Aggregates are also very useful in combination with <literal>GROUP    BY</literal> clauses.  For example, we can get the maximum low    temperature observed in each city with<programlisting>SELECT city, max(temp_lo)    FROM weather    GROUP BY city;</programlisting><screen>     city      | max---------------+----- Hayward       |  37 San Francisco |  46(2 rows)</screen>    which gives us one output row per city.  Each aggregate result is    computed over the table rows matching that city.    We can filter these grouped    rows using <literal>HAVING</literal>:<programlisting>SELECT city, max(temp_lo)    FROM weather    GROUP BY city    HAVING max(temp_lo) < 40;</programlisting><screen>  city   | max---------+----- Hayward |  37(1 row)</screen>    which gives us the same results for only the cities that have all    <literal>temp_lo</> values below 40.  Finally, if we only care about    cities whose    names begin with <quote><literal>S</literal></quote>, we might do<programlisting>SELECT city, max(temp_lo)    FROM weather    WHERE city LIKE 'S%'<co id="co.tutorial-agg-like">    GROUP BY city    HAVING max(temp_lo) < 40;</programlisting>   <calloutlist>    <callout arearefs="co.tutorial-agg-like">     <para>      The <literal>LIKE</literal> operator does pattern matching and      is explained in <xref linkend="functions-matching">.     </para>    </callout>   </calloutlist>   </para>   <para>    It is important to understand the interaction between aggregates and    <acronym>SQL</acronym>'s <literal>WHERE</literal> and <literal>HAVING</literal> clauses.    The fundamental difference between <literal>WHERE</literal> and    <literal>HAVING</literal> is this: <literal>WHERE</literal> selects    input rows before groups and aggregates are computed (thus, it controls    which rows go into the aggregate computation), whereas    <literal>HAVING</literal> selects group rows after groups and    aggregates are computed.  Thus, the    <literal>WHERE</literal> clause must not contain aggregate functions;    it makes no sense to try to use an aggregate to determine which rows    will be inputs to the aggregates.  On the other hand,    <literal>HAVING</literal> clause always contains aggregate functions.    (Strictly speaking, you are allowed to write a <literal>HAVING</literal>    clause that doesn't use aggregates, but it's wasteful: The same condition    could be used more efficiently at the <literal>WHERE</literal> stage.)   </para>   <para>    Observe that we can apply the city name restriction in    <literal>WHERE</literal>, since it needs no aggregate.  This is    more efficient than adding the restriction to <literal>HAVING</literal>,    because we avoid doing the grouping and aggregate calculations    for all rows that fail the <literal>WHERE</literal> check.   </para>  </sect1>  <sect1 id="tutorial-update">   <title>Updates</title>   <indexterm zone="tutorial-update">    <primary>UPDATE</primary>   </indexterm>   <para>    You can update existing rows using the    <command>UPDATE</command> command.     Suppose you discover the temperature readings are    all  off  by 2 degrees as of November 28.  You may update the    data as follows:<programlisting>UPDATE weather    SET temp_hi = temp_hi - 2,  temp_lo = temp_lo - 2    WHERE date > '1994-11-28';</programlisting>   </para>   <para>    Look at the new state of the data:<programlisting>SELECT * FROM weather;     city      | temp_lo | temp_hi | prcp |    date---------------+---------+---------+------+------------ San Francisco |      46 |      50 | 0.25 | 1994-11-27 San Francisco |      41 |      55 |    0 | 1994-11-29 Hayward       |      35 |      52 |      | 1994-11-29(3 rows)</programlisting>   </para>  </sect1>  <sect1 id="tutorial-delete">   <title>Deletions</title>   <indexterm zone="tutorial-delete">    <primary>DELETE</primary>   </indexterm>   <para>    Suppose you are no longer interested in the weather of Hayward.    Then you can do the following to delete those rows from the table.    Deletions are performed using the <command>DELETE</command>    command:<programlisting>DELETE FROM weather WHERE city = 'Hayward';</programlisting>    All weather records belonging to Hayward are removed.<programlisting>SELECT * FROM weather;</programlisting><screen>     city      | temp_lo | temp_hi | prcp |    date---------------+---------+---------+------+------------ San Francisco |      46 |      50 | 0.25 | 1994-11-27 San Francisco |      41 |      55 |    0 | 1994-11-29(2 rows)</screen>   </para>   <para>    One should be wary of statements of the form<synopsis>DELETE FROM <replaceable>tablename</replaceable>;</synopsis>    Without a qualification, <command>DELETE</command> will    remove  <emphasis>all</>  rows from the given table, leaving it    empty.  The system will not request confirmation before    doing this!   </para>  </sect1> </chapter><!-- Keep this comment at the end of the fileLocal variables:mode:sgmlsgml-omittag:nilsgml-shorttag:tsgml-minimize-attributes:nilsgml-always-quote-attributes:tsgml-indent-step:1sgml-indent-data:tsgml-parent-document:nilsgml-default-dtd-file:"./reference.ced"sgml-exposed-tags:nilsgml-local-catalogs:("/usr/lib/sgml/catalog")sgml-local-ecat-files:nilEnd:-->

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -