Repository: pandas-dev/pandas

Issue:
DOC: clarify read_sql docstring on relation with other read_sql_ functions
We have 3 (!) functions for reading data from SQL:

`read_sql`
`read_sql_table`
`read_sql_query`

Definitely one of these can be removed.  Probably aiming at `read_sql_query`, since its functionality seems most similar to that of `read_sql`.

`read_sql_table` seems more like a convenience function in place of `SELECT * FROM <table>`, though one could argue that we could accept a table-name in `read_sql` to do the same thing.


Discussion:
Those multiple functions have been deliberately introduced when the sql module has been refactored to be based on sqlalchemy. 
If there is one function "not needed", it is `read_sql`, as this just does one of the other two. But, given convenience and backward compatibility, I would be -1 on removing that one.

> read_sql_table seems more like a convenience function in place of SELECT \* FROM \<table\>

`read_sql_table` is much more than convenience function around `SELECT * FROM table`, as only when reading a full table we can use the sql table metadata information to do type inference.

> though one could argue that we could accept a table-name in read_sql to do the same thing.

This is already the case.

Of course you could argue that both `read_sql_query` and `read_sql_table` could be removed, as you can do both with `read_sql`, but those have been introduces to be able to explicitly either read a query or a table, without the need that pandas guesses which one of the two you want.
>

> > though one could argue that we could accept a table-name in read_sql to do the same thing.
This is already the case.

Really?  Nowhere is that mention in the docs for `read_sql` (unless that's what "text object" means?).   I've been only using `read_sql` for executing SQL queries.

>  as only when reading a full table we can use the sql table metadata information to do type inference.

Hmmm...how would reading all remaining `n - 1` columns be able to get you type information about the first the column?  I'm pretty sure `pandas` does some kind of type inference regardless if you read the full table or not.
It is clearly mentioned in the note in the `read_sql` docstring:

```
This function is a convenience wrapper around ``read_sql_table`` and
``read_sql_query`` (and for backward compatibility) and will delegate
to the specific function depending on the provided input (database
table name or SQL query).  The delegated function might have more specific
notes about their functionality not listed here.
```

But it is correct this is missing in the 'sql' keyword explanation.

>  I'm pretty sure pandas does some kind of type inference regardless if you read the full table or not.

Yes, we infer based on the values we get back. But when reading a table we 'reflect' the sql table schema and inspect the actual types in the sql table.

> It is clearly mentioned in the note in the read_sql docstring:

Doh!  I completely missed that part (need more coffee perhaps?).  My bad 😄 

Alright, given that this is a delegate, I'm okay then with leaving all of it alone for now.  I will just update the docs on `read_sql` so that the note shows up earlier in the documentation.

Resolving patch:
diff --git a/pandas/io/sql.py b/pandas/io/sql.py
--- a/pandas/io/sql.py
+++ b/pandas/io/sql.py
@@ -337,15 +337,22 @@ def read_sql(sql, con, index_col=None, coerce_float=True, params=None,
     """
     Read SQL query or database table into a DataFrame.
 
+    This function is a convenience wrapper around ``read_sql_table`` and
+    ``read_sql_query`` (for backward compatibility). It will delegate
+    to the specific function depending on the provided input. A SQL query
+    will be routed to ``read_sql_query``, while a database table name will
+    be routed to ``read_sql_table``. Note that the delegated function might
+    have more specific notes about their functionality not listed here.
+
     Parameters
     ----------
     sql : string or SQLAlchemy Selectable (select or text object)
-        SQL query to be executed.
-    con : SQLAlchemy connectable(engine/connection) or database string URI
+        SQL query to be executed or a table name.
+    con : SQLAlchemy connectable (engine/connection) or database string URI
         or DBAPI2 connection (fallback mode)
+
         Using SQLAlchemy makes it possible to use any DB supported by that
-        library.
-        If a DBAPI2 object, only sqlite3 is supported.
+        library. If a DBAPI2 object, only sqlite3 is supported.
     index_col : string or list of strings, optional, default: None
         Column(s) to set as index(MultiIndex).
     coerce_float : boolean, default True
@@ -377,14 +384,6 @@ def read_sql(sql, con, index_col=None, coerce_float=True, params=None,
     -------
     DataFrame
 
-    Notes
-    -----
-    This function is a convenience wrapper around ``read_sql_table`` and
-    ``read_sql_query`` (and for backward compatibility) and will delegate
-    to the specific function depending on the provided input (database
-    table name or SQL query).  The delegated function might have more specific
-    notes about their functionality not listed here.
-
     See also
     --------
     read_sql_table : Read SQL database table into a DataFrame.


Test patch: