Archive for the ‘SQL’ Category.
2020-05-24, 17:49
Here’s a short overview of SQL joins, find the source code of the document attached to the PDF (use Adobe Reader to access it).
SQL Joins
\documentclass[12pt]{article}
\usepackage{xcolor}
\usepackage{arev}
\usepackage{attachfile}
\usepackage{tikz}
\usetikzlibrary{shapes,snakes}
\def\firstcircle{(0,0) circle (2cm)}
\def\secondcircle{(0:3cm) circle (2cm)}
\colorlet{circle edge}{blue!50}
\colorlet{circle area}{blue!20}
\colorlet{white area}{white}
\tikzset{
filled/.style={fill=circle area, draw=circle edge, thick},
outline/.style={draw=circle edge, thick},
white/.style={fill=white area, draw=circle edge, very thick}
}
\begin{document}
\textattachfile{\jobname.tex}{\LaTeX~Code}
\section{Inner Join}
Inner joins return those records, that are present in table 1 and table 2.
\begin{center}
\begin{tikzpicture}[scale=1, every node/.style={scale=1}] % Inner Join
\begin{scope}
\clip \firstcircle;
\fill[filled] \secondcircle;
\end{scope}
\draw[outline] \firstcircle node {A};
\draw[outline] \secondcircle node {B};
\end{tikzpicture}
\end{center}
\section{Left Join}
Every record from table 1 is returned, regardless if it has a matching record in table 2. If the record has a matching record in table 2 this record from table 2 is returned as well.
\begin{center}
\begin{tikzpicture}[scale=1, every node/.style={scale=1}] % Left Join
\begin{scope}
\clip \firstcircle;
\draw[filled] \firstcircle node {A}
\secondcircle;
\end{scope}
\draw[outline] \firstcircle
\secondcircle node {B};
\end{tikzpicture}
\end{center}
\clearpage
\section{Left Outer Join}
Those records from table 1 are returned, that do not have a match in table 2.
\begin{center}
\begin{tikzpicture}[scale=1, every node/.style={scale=1}] % Left Outer Join
\draw[filled] \firstcircle node {A};
\draw[white] \secondcircle node {B};
\draw[outline] \firstcircle node {A};
\end{tikzpicture}
\end{center}
\section{Right Join}
Every record from table 2 is returned, regardless if it has a matching record in table 1. If the record has a matching record in table 1 this record from table 1 is returned as well.
\begin{center}
\begin{tikzpicture}[scale=1, every node/.style={scale=1}] % Right Join
\begin{scope}
\clip \secondcircle;
\draw[filled] \firstcircle \secondcircle node {B};
\end{scope}
\draw[outline] \firstcircle node {A} \secondcircle;
\end{tikzpicture}
\end{center}
\clearpage
\section{Right Outer Join}
Those records from table 2 are returned, that do not have a match in table 1.
\begin{center}
\begin{tikzpicture}[scale=1, every node/.style={scale=1}] % Right Join 2
\draw[filled] \secondcircle node {B};
\draw[white] \firstcircle node {A};
\draw[outline] \secondcircle node {B};
\end{tikzpicture}
\end{center}
\section{Theta Join}
Every row from dataset 1 is multiplied by every row of dataset 2. Usually a mistake unless you really want this Cartesian product.
\begin{center}
\begin{tikzpicture}[scale=1, every node/.style={scale=1}] % Theta
\draw[filled] \firstcircle node {A} \secondcircle node {B};
\end{tikzpicture}
\end{center}
\clearpage
\section{Full Outer}
Returns all records from table 1 and table 2 regardless if they have matches in the other table. Records, that do match, are linked together via key.
\begin{center}
\begin{tikzpicture}[scale=1, every node/.style={scale=1}] % Full Outer
\draw[filled] \firstcircle node {A};
\draw[filled] \secondcircle node {B};
\begin{scope}
\clip \firstcircle;
\fill[white] \secondcircle;
\draw[outline] \secondcircle;
\draw[outline] \firstcircle;
\end{scope}
\end{tikzpicture}
\end{center}
\end{document} |
\documentclass[12pt]{article}
\usepackage{xcolor}
\usepackage{arev}
\usepackage{attachfile}
\usepackage{tikz}
\usetikzlibrary{shapes,snakes}
\def\firstcircle{(0,0) circle (2cm)}
\def\secondcircle{(0:3cm) circle (2cm)}
\colorlet{circle edge}{blue!50}
\colorlet{circle area}{blue!20}
\colorlet{white area}{white}
\tikzset{
filled/.style={fill=circle area, draw=circle edge, thick},
outline/.style={draw=circle edge, thick},
white/.style={fill=white area, draw=circle edge, very thick}
}
\begin{document}
\textattachfile{\jobname.tex}{\LaTeX~Code}
\section{Inner Join}
Inner joins return those records, that are present in table 1 and table 2.
\begin{center}
\begin{tikzpicture}[scale=1, every node/.style={scale=1}] % Inner Join
\begin{scope}
\clip \firstcircle;
\fill[filled] \secondcircle;
\end{scope}
\draw[outline] \firstcircle node {A};
\draw[outline] \secondcircle node {B};
\end{tikzpicture}
\end{center}
\section{Left Join}
Every record from table 1 is returned, regardless if it has a matching record in table 2. If the record has a matching record in table 2 this record from table 2 is returned as well.
\begin{center}
\begin{tikzpicture}[scale=1, every node/.style={scale=1}] % Left Join
\begin{scope}
\clip \firstcircle;
\draw[filled] \firstcircle node {A}
\secondcircle;
\end{scope}
\draw[outline] \firstcircle
\secondcircle node {B};
\end{tikzpicture}
\end{center}
\clearpage
\section{Left Outer Join}
Those records from table 1 are returned, that do not have a match in table 2.
\begin{center}
\begin{tikzpicture}[scale=1, every node/.style={scale=1}] % Left Outer Join
\draw[filled] \firstcircle node {A};
\draw[white] \secondcircle node {B};
\draw[outline] \firstcircle node {A};
\end{tikzpicture}
\end{center}
\section{Right Join}
Every record from table 2 is returned, regardless if it has a matching record in table 1. If the record has a matching record in table 1 this record from table 1 is returned as well.
\begin{center}
\begin{tikzpicture}[scale=1, every node/.style={scale=1}] % Right Join
\begin{scope}
\clip \secondcircle;
\draw[filled] \firstcircle \secondcircle node {B};
\end{scope}
\draw[outline] \firstcircle node {A} \secondcircle;
\end{tikzpicture}
\end{center}
\clearpage
\section{Right Outer Join}
Those records from table 2 are returned, that do not have a match in table 1.
\begin{center}
\begin{tikzpicture}[scale=1, every node/.style={scale=1}] % Right Join 2
\draw[filled] \secondcircle node {B};
\draw[white] \firstcircle node {A};
\draw[outline] \secondcircle node {B};
\end{tikzpicture}
\end{center}
\section{Theta Join}
Every row from dataset 1 is multiplied by every row of dataset 2. Usually a mistake unless you really want this Cartesian product.
\begin{center}
\begin{tikzpicture}[scale=1, every node/.style={scale=1}] % Theta
\draw[filled] \firstcircle node {A} \secondcircle node {B};
\end{tikzpicture}
\end{center}
\clearpage
\section{Full Outer}
Returns all records from table 1 and table 2 regardless if they have matches in the other table. Records, that do match, are linked together via key.
\begin{center}
\begin{tikzpicture}[scale=1, every node/.style={scale=1}] % Full Outer
\draw[filled] \firstcircle node {A};
\draw[filled] \secondcircle node {B};
\begin{scope}
\clip \firstcircle;
\fill[white] \secondcircle;
\draw[outline] \secondcircle;
\draw[outline] \firstcircle;
\end{scope}
\end{tikzpicture}
\end{center}
\end{document}
Schlagwörter:
TikZ,
Joins,
SQL Category:
SQL |
Kommentare deaktiviert für Overviews of SQL Joins (with LaTeX code)
2020-05-17, 20:05
Ich habe seit ein paar Monaten wieder verstärkt Gelegenheit, meine rostigen SQL-Kenntnisse aufzufrischen. Kürzlich bin ich dabei an einer kleinen Herausforderung vorbeigekommen, die mich doch ein paar Minuten mehr beschäftigt hat. Gegeben sind zwei Tabellen, Namen und Adressen.
Namen
| ID |
Name |
| 1 |
Anna Amsel |
| 2 |
Bernd Borstel |
| 3 |
Cesar Causel |
| 4 |
Dagmal Dack |
Adressen
| ID |
NameID |
Adresse |
| 1 |
1 |
Amselweg 2 |
| 2 |
2 |
Badgasse 34 |
| 3 |
3 |
Chausseeweg 123 |
| 4 |
3 |
Dorfstraße 34 |
| 5 |
1 |
Alabasterpfad 32 |
ID ist jeweils der Primary Key, NameID der Fremdschlüssel von Adressen auf Namen. Ziel der Übung ist es, alle Namen mit der (sofern vorhanden) aktuellsten Adresse abzufragen.
Ein inner join bringt ganz klar das falsche Ergebnis, denn Dagmar Dack fehlt in der Ergebnismenge, Anna und Cesar sind zweimal vertreten.
SELECT n.Name, a.Adresse FROM Namen n JOIN Adressen a ON n.ID = a.NameID ; |
SELECT n.Name, a.Adresse from Namen n JOIN Adressen a on n.ID = a.NameID ;
Ein left join muss her, was das Ergebnis aber nur ein wenig besser macht: Dagmar ist jetzt drin, Anna und Cesar aber immer noch doppelt:
SELECT n.Name, a.Adresse FROM Namen n JOIN Adressen a ON n.ID = a.NameID ; |
SELECT n.Name, a.Adresse from Namen n JOIN Adressen a on n.ID = a.NameID ;
Beholfen habe ich mir dann mit einem Subselect:
SELECT n.Name, a.Adresse FROM Namen n
LEFT JOIN (SELECT MAX(ID) ID, MIN(NameID) NameID, MIN(Adresse) Adresse FROM Adressen GROUP BY NameID) a
ON n.ID = a.NameID |
select n.Name, a.Adresse from Namen n
left join (select max(ID) ID, min(NameID) NameID, min(Adresse) Adresse from Adressen group by NameID) a
on n.ID = a.NameID
Ergebnis
| Name |
Adresse |
| Anna Amsel |
Alabasterpfad 32
|
| Bernd Borstel |
Badgasse 34 |
| Cesar Causel |
Chausseeweg 123 |
| Dagmal Dack |
NULL |
Schlagwörter:
SQL,
Join Category:
SQL |
Kommentare deaktiviert für SQL: Nur den aktuellsten Eintrag aus einer gejointen Tabelle laden
2020-03-28, 23:48
Hier ein einfaches Beispiel, wie man die Daten aus der Nordwind-Datenbank in einen pandas Dataframe bekommt. Der originale Code stammt von https://pythontic.com/pandas/serialization/mysql und wurde auf meine Datenbank angepasst.
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine
import pymysql
import pandas as pd
sqlEngine = create_engine('mysql+pymysql://nwread:northwind@192.168.0.60/northwind', pool_recycle=3600)
dbConnection = sqlEngine.connect()
frame = pd.read_sql("select * from products", dbConnection);
pd.set_option('display.expand_frame_repr', False)
print(frame)
frame.to_excel('r:/abc.xlsx')
dbConnection.close() |
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine
import pymysql
import pandas as pd
sqlEngine = create_engine('mysql+pymysql://nwread:northwind@192.168.0.60/northwind', pool_recycle=3600)
dbConnection = sqlEngine.connect()
frame = pd.read_sql("select * from products", dbConnection);
pd.set_option('display.expand_frame_repr', False)
print(frame)
frame.to_excel('r:/abc.xlsx')
dbConnection.close()
2020-03-22, 19:46
Um aus dem lokalen Netz Zugriff auf die Nordwind-DB zu erhalten, muss man folgendes tun:
- die Datei
50-server.cnf in /etc/mysql/mariadb.conf.d bearbeiten. Hier statt 127.0.0.1 die IP-Adresse des Servers eingeben. An dieses Interface wird MariaDB gebunden.
- einen neuen Nutzer anlegen:
CREATE USER 'nwread' IDENTIFIED BY 'northwind';
- Zugriff aus dem Netz für diesen User erteilen:
GRANT USAGE ON *.* TO 'nwread'@'%' IDENTIFIED BY 'northwind';
Kann sein, dass dieses Statement schon ausreichend ist, das werde ich noch überprüfen. Ich habe aber zusätzlich noch ausgeführt:
- Zugriff auf die Datenbank geben:
GRANT ALL privileges ON `northwind`.* TO 'nwread'@'%';
Nach dem Neustarts des MariaDB-Servers klappt der Zugriff, beispielsweise über HeidiSQL, das ich sehr empfehlen kann.
2020-03-20, 19:46
Mit der Nordwind (Northwind) Datenbank gibt es eine ursprünglich für MS Access entwickelte Datenbank, an der sich viele SQL-Konstrukte üben lassen. Die Datenbank gibt es auch für MySQL, unter anderem unter https://github.com/dalers/mywind.
Hier nun die notwendigen Schritte für das Einspielen in eine MySQL/MariaDB-Datenbank:
- git clone https://github.com/dalers/mywind.git
- cd mywind
- sudo mariadb < northwind.sql
- sudo mariadb < northwind-data.sql
Mittels SQL kann man jetzt prüfen, ob die Daten vollständig geladen wurden:
- sudo mariadb
- use northwind
- select count(*) from products;
bringt eine Zeilenzahl von 45 Zeilen.
2020-03-20, 19:16
Für Apache Guacamole brauchte ich einen MySQL/MariaDB Server auf meinem Linux-Server, hier die Schritte zur Installation:
- sudo apt update
- sudo apt upgrade
- sudo apt install mariadb-server
- sudo mariadb
Standardmäßig kommt man als root sofort in die Datenbank, ohne ein Passwort einzugeben. Ich bin zwar den Hinweisen von https://kofler.info/root-login-problem-mit-mariadb/ gefolgt, um für den root-User ebenfalls ein Passwort festzulegen.
Aktuell wird aber jedes Passwort akzeptiert, wenn ich root bin, jedoch das festgelegte Passwort nicht akzeptiert, wenn ich als normaler User mysql -u root -p ausführe.
Sinnvolle mysql/mariadb-Befehle
2018-05-13, 18:14
A while ago I had some issues retrieving data from MySQL using Python, as my Python was more up-to-date than the official bindings. A few days ago I found a nice GIST (https://gist.github.com/stefanthoss/364b2a99521d5bb76d51) that uses pymysql:
import pandas as pd
import pymysql
from sqlalchemy import create_engine
engine = create_engine('mysql+pymysql://<user>:<password>@<host>[:<port>]/<dbname>')
df = pd.read_sql_query('SELECT * FROM table', engine)
df.head() |
import pandas as pd
import pymysql
from sqlalchemy import create_engine
engine = create_engine('mysql+pymysql://<user>:<password>@<host>[:<port>]/<dbname>')
df = pd.read_sql_query('SELECT * FROM table', engine)
df.head()
2018-05-13, 17:46
Graphviz ist seit Jahrzehnten das Tool, um Graphen zu erstellen. Für Visual Studio Code gibt es mit dem „Graphviz Preview“ Plugin die Möglichlkeit, eine Echtzeit-Preview zu erhalten. Dann fühlt es sich fast an wie Visio 🙂
Hier die Quelle für diesen Tipp: https://spin.atomicobject.com/2017/11/15/table-rel-diagrams-graphviz/
Tipp: Graphviz muss natürlich installiert und im Pfad sein, die Preview aktiviert man dann in VSC über –-P ==> „Graphviz: Show Preview“.

Category:
Programmierung,
SQL |
Kommentare deaktiviert für Graphviz Dateien mit Autopreview erstellen
2014-11-07, 19:23
Today I needed to split an integer (representing a bitmask) into its components, each component in a separate column. The following code from http://www.sqlservercentral.com/Forums/Topic1101943-392-1.aspx did the trick.
SELECT
N,
SIGN(N & 1) AS Bit1,
SIGN(N & 2) AS Bit2,
SIGN(N & 4) AS Bit3,
SIGN(N & 8) AS Bit4,
SIGN(N & 16) AS Bit5,
SIGN(N & 32) AS Bit6,
SIGN(N & 64) AS Bit7,
SIGN(N & 128) AS Bit8
FROM (
SELECT 511
) TestData(N) |
SELECT
N,
SIGN(N & 1) AS Bit1,
SIGN(N & 2) AS Bit2,
SIGN(N & 4) AS Bit3,
SIGN(N & 8) AS Bit4,
SIGN(N & 16) AS Bit5,
SIGN(N & 32) AS Bit6,
SIGN(N & 64) AS Bit7,
SIGN(N & 128) AS Bit8
FROM (
SELECT 511
) TestData(N)
Category:
Programmierung,
SQL |
Kommentare deaktiviert für SQL: Splitting a Bitmask into separate columns
2014-01-05, 22:37
Ich bereite momentan die Spendenquittungen der Dingfabrik mit Python, Jinja2, MySQL und LaTeX auf. Um den SQL Code sauber zu halten, lagere ich einiges aus dem Python-Code in MySQL Funktionen aus.
Hier ein einfaches Beispiel, das basierend auf Parametern für Mitglieds-ID und Namenstyp entweder der Vornamen, Nachnamen oder kompletten Namen eines Mitglieds zurückgibt.
DROP FUNCTION IF EXISTS fs_getname;
DELIMITER $$
CREATE FUNCTION fs_getname(nummer INT, typ CHAR)
RETURNS VARCHAR(100)
NOT DETERMINISTIC
BEGIN
IF typ = 'c' THEN
RETURN (SELECT TRIM(CONCAT(COALESCE(Vorname,"")," ",COALESCE(Name," "))) FROM Stammdaten WHERE ID = nummer);
ELSEIF typ = 'f' THEN
RETURN (SELECT COALESCE(Vorname,"") FROM Stammdaten WHERE ID = nummer);
ELSEIF typ = 'l' THEN
RETURN (SELECT COALESCE(Name,"") FROM Stammdaten WHERE ID = nummer);
END IF;
END$$
DELIMITER ; |
DROP FUNCTION IF EXISTS fs_getname;
DELIMITER $$
CREATE FUNCTION fs_getname(nummer int, typ char)
RETURNS VARCHAR(100)
NOT DETERMINISTIC
BEGIN
IF typ = 'c' THEN
RETURN (SELECT TRIM(CONCAT(Coalesce(Vorname,"")," ",Coalesce(Name," "))) FROM Stammdaten WHERE ID = nummer);
ELSEIF typ = 'f' THEN
RETURN (SELECT Coalesce(Vorname,"") FROM Stammdaten WHERE ID = nummer);
ELSEIF typ = 'l' THEN
RETURN (SELECT Coalesce(Name,"") FROM Stammdaten WHERE ID = nummer);
END IF;
END$$
DELIMITER ;