tsunami
Goto Top

Mysql query mit Bedingung

Hallo zusammen,
ich habe ein Formular mit 3 select-Feldern. Monat, Kunde und Mitarbeiter.
Daraus soll eine dynamische DB Abfrage entstehen.
So, nun kann ich natürlich mit php 8 verschiedene ifs bauen. Es soll entweder gefiltert werden, wenn zB ein spezifischer Kunde gewählt wurde, wenn kein spezifischer Kunde gewählt wurde, sollen alle Datensätze angezeigt werden.
Also kunde spezifisch ja nein, Mitarbeiter spezifisch ja nein, Datum spezifisch ja nein:

select taetigkeiten.*,taetigkeiten.id as tid, mitarbeiter.kuerzel,mitarbeiter.ausbildung,mitarbeiter.name as mitarbeiter,kunden.*,kunden.id as kid, infoarten.name as infoart
from infoarten,taetigkeiten,mitarbeiter,kunden
where taetigkeiten.kunde=%s
and taetigkeiten.ausfuehrender=%s
and taetigkeiten.ausfuehrender=mitarbeiter.id
and infoarten.id=taetigkeiten.informationsart_id
and taetigkeiten.kunde=kunden.id
and datum like '%s%%' order by datum   

Was ich bräuchte ist sowas wie:
select taetigkeiten.*,taetigkeiten.id as tid, mitarbeiter.kuerzel,mitarbeiter.ausbildung,mitarbeiter.name as mitarbeiter,kunden.*,kunden.id as kid, infoarten.name as infoart
from infoarten,taetigkeiten,mitarbeiter,kunden
where if(kunde==0;mache nichts;ansonsten kunde == 4)
and if(taetigkeiten.ausfuehrender==0;mache nichts;ansonsten taetigkeiten.ausfuehrender==21
and infoarten.id=taetigkeiten.informationsart_id
and taetigkeiten.kunde=kunden.id
and if(datum==0;mache nichts; ansonsten datum like '2021-05%' order by datum   

Ich hatte gesehen, dass es so was ähnliches mit case gibt, aber das war nur für die Ergebnisse. Also was weiß ich case monat=10 jahrezeit = Herbst.
Mein Problem ist, dass dann natürlich das "from kunden" nicht komplett rein darf, wenn kein Kunde gewählt ist. Lasse ich es weg, kennt er die Tabelle nicht. weil es sonst zuviele Datensätze ausgibt. Hatte noch versucht, dass um Codeschipsel zu erweitern.

$schnipselfuerkunde=" and taetigkeiten.kunde=".$kundeid." and taetigkeiten.kunde= kunden.id";   

Funktioniert nur für einen Teil der Kombis, weil je nach Filter der from - Teil unterschiedlich ist.

Rauskommen soll eine flexible Tabelle. Wo ich entweder sehen kann, wo der Mitarbeiter war, wo der Mitarbeiter am Monat x war. wann der Mitarbeiter beim Kunden A war und andersherum, wer beim Kunden A war, wer im Monat M beim Kunden A war, oder was im Monat 11 2021 gelaufen ist.
Der Tabellenaufbau:

-- phpMyAdmin SQL Dump
-- version 4.9.0.1
-- https://www.phpmyadmin.net/
--
-- Host: 127.0.0.1
-- Erstellungszeit: 14. Mrz 2022 um 10:40
-- Server-Version: 10.3.16-MariaDB
-- PHP-Version: 7.2.20

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";  
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";  


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;

--
-- Datenbank: `dummy`
--

-- --------------------------------------------------------

--
-- Tabellenstruktur für Tabelle `taetigkeitendemo`
--

CREATE TABLE `taetigkeitendemo` (
`id` int(11) NOT NULL,
`datum` datetime NOT NULL,
`kunde` int(5) NOT NULL,
`ausfuehrender` int(11) NOT NULL,
`prioritaet` int(1) NOT NULL,
`informationsart_id` int(1) NOT NULL,
`beschreibung` text COLLATE latin1_german1_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_german1_ci;

--
-- Indizes der exportierten Tabellen
--

--
-- Indizes für die Tabelle `taetigkeitendemo`
--
ALTER TABLE `taetigkeitendemo`
ADD PRIMARY KEY (`id`);

--
-- AUTO_INCREMENT für exportierte Tabellen
--

--
-- AUTO_INCREMENT für Tabelle `taetigkeitendemo`
--
ALTER TABLE `taetigkeitendemo`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
COMMIT;

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
Die Kunden und die Mitarbeiter sind via id verknüpft, das heißt ja, dass je nach Filter "from mitarbeiter" rein muss oder nicht. (oder "from kunden")
mfG

Content-ID: 2163545354

Url: https://administrator.de/contentid/2163545354

Ausgedruckt am: 24.11.2024 um 05:11 Uhr

em-pie
em-pie 14.03.2022 aktualisiert um 18:28:01 Uhr
Goto Top
Moin,

eigentlich brauchst du keine If-Bedingungen.

Du kannst das wie folgt machen - und dabei mit JOINs arbeiten, was IMHO sinniger ist

SELECT
 @postKunde
 , @postMitarbeiter
 , @postDatum

SET 
 @postKunde = NULLIF(4711, 0)
 , @postMitarbeiter = NULLIF(815, 0)
 , @postDatum = NULLIF('14.03.2022', '')  

SELECT
 taetigkeiten.*
 , mitarbeiter.kuerzel
 , mitarbeiter.ausbildung
 , mitarbeiter.name as mitarbeiter
 , kunden.*
 , ia.name as infoart

from taetigkeiten as t

INNER JOIN kunden as k
 on t.kunde = k.id
INNER JOIN mitarbeiter as m
 on t.ausfuehrender = m.id
INNER JOIN infoarten as i
 on t.informationsart_id = i.ID

WHERE 
 (t.kunde = @postKunde or @postKunde is null)
 and (t.ausfuehrender = @postMitarbeiter or @postMitarbeiter is null)
 and (t.datum = @postDatum or @postDatum is null)

ORDER BY
 t.datum

die drei Variable im Set übernimmst du dann aus deinen Auswahlfeldern, die du (vermutlich) per POST oder was auch immer übergibst

Gruß
em-pie
akretschmer
akretschmer 14.03.2022 um 19:38:30 Uhr
Goto Top
tsunami
tsunami 15.03.2022 um 08:25:14 Uhr
Goto Top
@em-pie
Genau, die 3 Selects kommen via post.
$kunde=0;
if(isset($_POST['kunde']))  
$kunde=$_POST['kunde'];  
Die Variable Kunde ist also entweder 0 => Filter ignorieren
oder !=0 => Filter

Was bedeutet der Part:
@postMitarbeiter
Ist das exemplarisch für die Variable Kunde?
em-pie
Lösung em-pie 15.03.2022 aktualisiert um 08:40:30 Uhr
Goto Top
Zitat von @tsunami:

@em-pie
Genau, die 3 Selects kommen via post.
$kunde=0;
if(isset($_POST['kunde']))  
$kunde=$_POST['kunde'];  
Die Variable Kunde ist also entweder 0 => Filter ignorieren
oder !=0 => Filter
Die Zeilen 1-4 deklarieren grundsätzlich erst einmal Variablen innerhalb des SQL-Statements
Die Zeilen 6-9 weisen den Variablen Werte zu. Hier kannst du eine via POST erhaltenen Variablen einfügen *


Was bedeutet der Part:
@postMitarbeiter
Ist das exemplarisch für die Variable Kunde?
Nein. Du hast doch in deinem Ausgangspost selbst mitgeteilt, dass Mitarbeiter der der Ausfuehrer ist.
Also ist der Mitarbeiter dein eigenes Personal

Ich habe die Variablen alle mit @post begonnen, um optisch darauf hinzuweisen, dass die Inhalte aus einem POST-Statement stammen. Ich hätte auch die Variablen @pusemuckel, @8041 und @Gandalf nennen können, wäre dann aber weniger eindeutig gewesen.

Versuche bitte zu verstehen, was oben passiert. Es erfüllt eigentlich genau deine Anforderung. Deine Filterung findet ja erst in den Zeilen 28 - 31 statt. Wobei nicht gegen 0 geprüft wird, sondern NULL (das eine ist die Zahl 0 das andere ist nichts). Wenn Kunde bzw. Mitarbeiter den Wert 0 inne haben, werden diese auf NULL gesetzt (siehe Zeile 6 - 9).
Also ist der Kunde = Variable oder die Variable ist leer (und somit werden alle Kunden gelistet)


(*) Hierzu noch eine Anmerkung
Prüfe bitte noch, ob die Inhalte valide sind. Der nächst beste pöhse Pursche fängt sonst mit SQL-Injections an!

Edit: Typo
tsunami
tsunami 16.03.2022 um 16:51:18 Uhr
Goto Top
@em-pie
Irgndwie hakt es noch:
Zu einen irritiert mich das "@"
 
@postKunde = NULLIF(4711, 0)
 , @postMitarbeiter = NULLIF(815, 0)
 , @postDatum = NULLIF('14.03.2022', '')  

Das macht dasselbe, ich ich mit if(isset(...) gemacht habe? Gegen das sql-Injection nehme ich möglichst das sprintf mit dem mysqli_real_escape_string)

SELECT t.* , m.kuerzel , m.ausbildung , m.name as mitarbeiter , k.* , i.name as infoart from taetigkeiten as t INNER JOIN kunden as k on t.kunde = k.id INNER JOIN mitarbeiter as m on t.ausfuehrender = m.id INNER JOIN infoarten as i on t.informationsart_id = i.ID WHERE (t.kunde = 0 or 0 = 0 ) and (t.ausfuehrender = 2 or 2 = 0) and (t.datum like '2021-10%' or '2021-10' =0) ORDER BY t.datum  

So scheint es zu funktionieren. den Part mit Nullif habe ich getauscht. Was mich fuchst, ist der from part. taetigkeiten brauche ich in jedem Fall, mitarbeiter nur, wenn ich den entsprechenden Filter gesetzt habe. Das scheint ja das inner join zu machen... Ich würde es gerne verstehen.
Vielen Dank erstmal.
em-pie
Lösung em-pie 17.03.2022 aktualisiert um 10:51:23 Uhr
Goto Top
Moin,

Ein Tipp: Formatiere deine SQL-Queries (und auch andere Quellcodes) ordentlich. das vereinfacht das Lesen ungemein.

Zu deinem Problem.
Mein Code oben ist ausschließlich SQL-Syntax. PHP streut da noch nicht ein.
Im SQL-Statement kann man mit Variablen arbeiten, erkennbar an einem @. Beginnt die Variable mit einem @@, so hadelt es sich um Systemvariablen.

In deinem Fall müssest du das, um das in PHP einzubinden, wie folgt aufbauen:
<?php
$kunde = 4711;  //der Inhalt aus deinem POST. Habe es hier stark abgekürzt
$mitarbeiter = 815;  //der Inhalt aus deinem POST. Habe es hier stark abgekürzt
$datum = "17.03.2022";  //der Inhalt aus deinem POST. Habe es hier stark abgekürzt  


 $strSqlQry = "SELECT  
   @postKunde
   , @postMitarbeiter
   , @postDatum

 SET 
   @postKunde = NULLIF('" . $kunde . "', 0)  
   , @postMitarbeiter = NULLIF('" . $mitarbeiter . "', 0)  
   , @postDatum = NULLIF('". $datum . "', '')  

 SELECT
   taetigkeiten.*
   , mitarbeiter.kuerzel
   , mitarbeiter.ausbildung
   , mitarbeiter.name as mitarbeiter
   , kunden.*
   , ia.name as infoart

 FROM taetigkeiten as t

 INNER JOIN kunden as k
   on t.kunde = k.id
 INNER JOIN mitarbeiter as m
   on t.ausfuehrender = m.id
 INNER JOIN infoarten as i
   on t.informationsart_id = i.ID

 WHERE 
   (t.kunde = @postKunde or @postKunde is null)
   and (t.ausfuehrender = @postMitarbeiter or @postMitarbeiter is null)
   and (t.datum = @postDatum or @postDatum is null)

 ORDER BY
   t.datum";  
?>

Die PHP-Variable $strSqlQry ist dann deine, mit der du das Statement "abfeuern" kannst.

Edit: Typo
tsunami
tsunami 17.03.2022 um 10:39:34 Uhr
Goto Top
Vielen Dank! Tiuts!