|
394 | 394 | "Na prozkoumání struktury a obsahu databáze můžete použít nějaký specializovaný program - [DB Browser](https://sqlitebrowser.org/), [DBeaver](https://dbeaver.io/), [MySQL Workbench](https://www.mysql.com/products/workbench/), ... je jich hodně, typicky se specializují na konkrétní druh databáze, některé programy jsou zdarma a některé placené. Existují i webové aplikace, nejznámější asi český [Adminer](https://www.adminer.org/). Zde jsem vám chtěl ukázat, že toho samého se dá dosáhnout i takto z Pythonu." |
395 | 395 | ] |
396 | 396 | }, |
| 397 | + { |
| 398 | + "cell_type": "code", |
| 399 | + "execution_count": null, |
| 400 | + "metadata": {}, |
| 401 | + "outputs": [], |
| 402 | + "source": [ |
| 403 | + "Poznámka: struktura této databáze je trochu jiná, než byl motivační příklad na začátku. Nem" |
| 404 | + ] |
| 405 | + }, |
397 | 406 | { |
398 | 407 | "cell_type": "markdown", |
399 | 408 | "metadata": {}, |
|
1912 | 1921 | " ''', engine)" |
1913 | 1922 | ] |
1914 | 1923 | }, |
| 1924 | + { |
| 1925 | + "cell_type": "markdown", |
| 1926 | + "metadata": {}, |
| 1927 | + "source": [ |
| 1928 | + "To GROUP BY je potřeba, protože bez toho se bude *celá* tabulka považovat za jedinou *skupinu* a použití agregačních funkcí způsobí to, že se vám vrátí jen jeden řádek výsledků:" |
| 1929 | + ] |
| 1930 | + }, |
| 1931 | + { |
| 1932 | + "cell_type": "code", |
| 1933 | + "execution_count": 59, |
| 1934 | + "metadata": {}, |
| 1935 | + "outputs": [ |
| 1936 | + { |
| 1937 | + "data": { |
| 1938 | + "text/html": [ |
| 1939 | + "<div>\n", |
| 1940 | + "<style scoped>\n", |
| 1941 | + " .dataframe tbody tr th:only-of-type {\n", |
| 1942 | + " vertical-align: middle;\n", |
| 1943 | + " }\n", |
| 1944 | + "\n", |
| 1945 | + " .dataframe tbody tr th {\n", |
| 1946 | + " vertical-align: top;\n", |
| 1947 | + " }\n", |
| 1948 | + "\n", |
| 1949 | + " .dataframe thead th {\n", |
| 1950 | + " text-align: right;\n", |
| 1951 | + " }\n", |
| 1952 | + "</style>\n", |
| 1953 | + "<table border=\"1\" class=\"dataframe\">\n", |
| 1954 | + " <thead>\n", |
| 1955 | + " <tr style=\"text-align: right;\">\n", |
| 1956 | + " <th></th>\n", |
| 1957 | + " <th>COUNT(*)</th>\n", |
| 1958 | + " <th>MIN(birth_date)</th>\n", |
| 1959 | + " <th>MAX(birth_date)</th>\n", |
| 1960 | + " </tr>\n", |
| 1961 | + " </thead>\n", |
| 1962 | + " <tbody>\n", |
| 1963 | + " <tr>\n", |
| 1964 | + " <th>0</th>\n", |
| 1965 | + " <td>7527</td>\n", |
| 1966 | + " <td>1857-11-11</td>\n", |
| 1967 | + " <td>2008-06-02</td>\n", |
| 1968 | + " </tr>\n", |
| 1969 | + " </tbody>\n", |
| 1970 | + "</table>\n", |
| 1971 | + "</div>" |
| 1972 | + ], |
| 1973 | + "text/plain": [ |
| 1974 | + " COUNT(*) MIN(birth_date) MAX(birth_date)\n", |
| 1975 | + "0 7527 1857-11-11 2008-06-02" |
| 1976 | + ] |
| 1977 | + }, |
| 1978 | + "execution_count": 59, |
| 1979 | + "metadata": {}, |
| 1980 | + "output_type": "execute_result" |
| 1981 | + } |
| 1982 | + ], |
| 1983 | + "source": [ |
| 1984 | + "pd.read_sql_query('''\n", |
| 1985 | + " SELECT COUNT(*), MIN(birth_date), MAX(birth_date)\n", |
| 1986 | + " FROM actors \n", |
| 1987 | + " ''', engine)" |
| 1988 | + ] |
| 1989 | + }, |
| 1990 | + { |
| 1991 | + "cell_type": "markdown", |
| 1992 | + "metadata": {}, |
| 1993 | + "source": [ |
| 1994 | + "Jaký je rozdíl mezi `COUNT(*)`, `COUNT(id)` a `COUNT(něco)`?\n", |
| 1995 | + "\n", |
| 1996 | + "`COUNT(*)` vrací počet řádků. `COUNT(sloupec)` vrací počet řádků, ve kterých je v daném sloupci nějaká hodnota (tj. není tam NULL). Pokud tím sloupcem je `id`, který je téměř vždy NON-NULL, tak je `COUNT(id)` a `COUNT(*)` vlastně to samé :)\n" |
| 1997 | + ] |
| 1998 | + }, |
1915 | 1999 | { |
1916 | 2000 | "cell_type": "code", |
1917 | | - "execution_count": 32, |
| 2001 | + "execution_count": 60, |
1918 | 2002 | "metadata": {}, |
1919 | 2003 | "outputs": [ |
1920 | 2004 | { |
|
1959 | 2043 | "0 7527 7527 5753" |
1960 | 2044 | ] |
1961 | 2045 | }, |
1962 | | - "execution_count": 32, |
| 2046 | + "execution_count": 60, |
1963 | 2047 | "metadata": {}, |
1964 | 2048 | "output_type": "execute_result" |
1965 | 2049 | } |
|
1971 | 2055 | " ''', engine)" |
1972 | 2056 | ] |
1973 | 2057 | }, |
| 2058 | + { |
| 2059 | + "cell_type": "markdown", |
| 2060 | + "metadata": {}, |
| 2061 | + "source": [ |
| 2062 | + "Jak je vidět, u některých herců není vyplněno `birth_date`." |
| 2063 | + ] |
| 2064 | + }, |
1974 | 2065 | { |
1975 | 2066 | "cell_type": "markdown", |
1976 | 2067 | "metadata": {}, |
|
1979 | 2070 | "\n", |
1980 | 2071 | "Ještě rekapitulace, jak se probíhá provádění SQL dotazu :)\n", |
1981 | 2072 | "\n", |
1982 | | - "1. databáze vezme tabulky vyjmenované ve FROM a JOIN\n", |
1983 | | - "2. databáze čte řádky (jeden po druhém) z těch tabulek (už spojené podle příslušných JOIN výrazů)\n", |
| 2073 | + "1. databáze vezme tabulky vyjmenované ve FROM\n", |
| 2074 | + "2. databáze čte řádky (jeden po druhém)\n", |
1984 | 2075 | "3. ty řádky se filtrují podle uvedených WHERE výrazů\n", |
1985 | 2076 | "4. přefiltrované řádky se seskupí podle GROUP BY výrazů do skupin\n", |
1986 | 2077 | "5. ty skupiny se filtrují pode uvedených HAVING výrazů\n", |
1987 | | - "6. to,\n", |
1988 | | - "\n", |
| 2078 | + "6. výsledek se seřadí podle ORDER BY\n", |
| 2079 | + "7. výsledek se ořízne podle LIMIT\n", |
1989 | 2080 | "\n", |
1990 | 2081 | "Probrali jsme jen to nejdůležitější. Pro představu, jaké jsou možnosti zápisu SELECT dotazu\n", |
1991 | 2082 | "(převzato z [dokumentace SQLite](https://www.sqlite.org/lang_select.html)):\n", |
|
2014 | 2105 | "source": [ |
2015 | 2106 | "## JOIN\n", |
2016 | 2107 | "\n", |
2017 | | - "TODO: tady bude ukázka JOIN v SQL vs. merge v DataFrame\n", |
| 2108 | + "JOIN je v SQL to samé, co je merge v DataFrame (viz některá předchozí hodina).\n", |
2018 | 2109 | "\n", |
2019 | 2110 | "<div><img src=\"https://naucse.python.cz/2020/pydata-praha-jaro/pydata/pandas_correlations/static/joins.svg\" width=400></div>" |
2020 | 2111 | ] |
2021 | 2112 | }, |
2022 | 2113 | { |
2023 | 2114 | "cell_type": "code", |
2024 | | - "execution_count": 33, |
| 2115 | + "execution_count": 61, |
2025 | 2116 | "metadata": {}, |
2026 | 2117 | "outputs": [ |
2027 | 2118 | { |
|
2188 | 2279 | "[9811 rows x 6 columns]" |
2189 | 2280 | ] |
2190 | 2281 | }, |
2191 | | - "execution_count": 33, |
| 2282 | + "execution_count": 61, |
2192 | 2283 | "metadata": {}, |
2193 | 2284 | "output_type": "execute_result" |
2194 | 2285 | } |
2195 | 2286 | ], |
2196 | 2287 | "source": [ |
2197 | 2288 | "pd.read_sql_query('''\n", |
2198 | 2289 | " SELECT movie_id, title, actor_id, name, a.id, m.id AS idecko_filmu\n", |
2199 | | - " FROM actors AS a\n", |
| 2290 | + " FROM actors AS a\n", |
2200 | 2291 | " LEFT JOIN movie_to_actor AS ma ON a.id = ma.actor_id\n", |
2201 | 2292 | " LEFT JOIN movies AS m ON m.id = ma.movie_id\n", |
2202 | 2293 | "''', engine)" |
|
2206 | 2297 | "cell_type": "markdown", |
2207 | 2298 | "metadata": {}, |
2208 | 2299 | "source": [ |
2209 | | - "## CREATE TABLE" |
| 2300 | + "## CREATE TABLE\n", |
| 2301 | + "\n", |
| 2302 | + "Pokud budeme chtít vytvořit novou tabulku, používá se k tomu příkaz CREATE TABLE.\n", |
| 2303 | + "Musíme vyjmenovat názvy a typy sloupců, které v tabulce chceme mít." |
| 2304 | + ] |
| 2305 | + }, |
| 2306 | + { |
| 2307 | + "cell_type": "code", |
| 2308 | + "execution_count": null, |
| 2309 | + "metadata": {}, |
| 2310 | + "outputs": [], |
| 2311 | + "source": [ |
| 2312 | + "pd.read_sql_query('''\n", |
| 2313 | + " CREATE TABLE pokus (\n", |
| 2314 | + " id INT PRIMARY KEY,\n", |
| 2315 | + " \n", |
| 2316 | + " ) \n", |
| 2317 | + "''', engine)" |
2210 | 2318 | ] |
2211 | 2319 | }, |
2212 | 2320 | { |
|
0 commit comments