MySQL Abfrage leere Fächer von bis

Thomas_Jung

Erfahrenes Mitglied
Hallo
Ich habe eine Tabelle mit den Feldern Lager ,Regal, Höhe ,Fach
Jede Höhe hat bis zu 30 Fächer .
Jetzt möchte ich wissen welche Fächer davon belegt sind. (Ist Null )
Das ist kein Problem jedes Fach einzeln abzufragen.
Das Ergebnis wäre
Lager. Regal. Höhe. Fach

1. 1. 1. 1 ist frei
1. 1. 1. 2 ist frei
1. 1. 1. 3 ist frei
1. 1. 1. 4 ist belegt
1. 1. 1. 5 ist frei
1. 1. 1. 6 ist frei
1. 1. 1. 7 ist frei
1. 1. 1. 8 ist belegt
1. 1. 1. 9 ist frei
U.s.w

Ich möchte aber das Ergebnis so haben

Fach 1-3 ist leer
Fach 5-7 ist leer

U.s.w
Kann mir einer einen Tipp geben wie ich das am besten anstelle

Gruß Thomas
 
Also in MySQL direkt wird es eher kompliziert. Du solltest einerseits die Fächer nicht mit ausgeben, die belegt sind, andererseits die Fächer nach ihrer "Nummer" (also beispielsweise 1.1.1.6) sortieren. Danach kannst du dann in PHP über diese Elemente iterieren und dabei achtest du darauf, in welcher Weise sich die Nummer im Vergleich zu dem Fach davor verändert. Ist die aktuelle Nummer um eins erhöht, dann gehört sie noch in den aktuellen Bereich, wenn nicht, dann wird der aktuelle Bereich abgeschlossen und ein neuer Bereich eröffnet, welcher bei der aktuellen Nummer beginnt.
PHP:
$items = array(
  '1.1.1.1',
  '1.1.1.2',
  '1.1.1.3',
  '1.1.1.5',
  '1.1.1.6',
  '1.1.1.7',
  '1.1.1.9'
);

$last = null;
$ranges = array();

foreach ( $items as $item ) {
  $number = explode( '.', $item );

  if ( $last === null ) {
    array_push( $ranges, array( $number ) );
    continue;
  }

  if ( $number[ 0 ] == $last[ 0 ] and $number[ 1 ] == $last[ 1 ]
    and $number[ 2 ] == $last[ 2 ] and $number[ 3 ] == ( $last[ 3 ] + 1 ) ) {
    $last = $number;
    continue;
  }
  
  $count = count( $ranges );
  $ranges[ $count - 1 ][ 1 ] = $last;
  $ranges[ $count     ][ 0 ] = $number;
  $last = $number;
}

$count = count( $ranges );
$ranges[ $count - 1 ][ 1 ] = $last;

foreach( $ranges as $range ) {
  list( $min, $max ) = $range;
  $min = array_pop( $min );
  $max = array_pop( $max );

  if ( $min === $max ) {
    echo 'Fach ' . $min;
  } else {
    echo 'Fach ' . $min . ' - ' . $max;
  }
}
 
Hi
Hatte es mir auch einfacher vorgestellt
Ich danke dir für das Beispiel.
Werde es morgen früh durcharbeiten und gebe dir morgen Bescheid.
 
Hi einfach nur crack

Ich erhalte bei der Ausgabe


HTML:
Warning: array_pop() expects parameter 1 to be array, null given 
Fach 1 -
Warning: array_pop() expects parameter 1 to be array, null given 
Fach 2 -
Warning: array_pop() expects parameter 1 to be array, null given 
Fach 3 -
Warning: array_pop() expects parameter 1 to be array, null given 
Fach 5 -
Warning: array_pop() expects parameter 1 to be array, null given 
Fach 6 -
Warning: array_pop() expects parameter 1 to be array, null given 
Fach 7 -
Warning: array_pop() expects parameter 1 to be array, null given 
Fach 9 -

Bei der Ausgabe von

PHP:
foreach( $ranges as $range ) { 
  list( $min, $max ) = $range;

echo 'Array MIN: '.print_r($min).'<br>'; 
echo 'Array MAX: '.print_r($max).'<br>';

Ist MIN immer1
Und Max immer 1

Könntes du nochmal über den Code schauen?

Gruß
Thomas
 
Sorry Crack, ich finde deine Lösung nicht besonders elegant und wartungsleicht. Man verstrickt sich zu schnell in die festen Index.

Ich würde es mehr so lösen. Damit kannm an auch über mehrere Lagerorte die Fächer auswerten. Dazu habe ich das Array mit den Leeren Fächern mal noch erweitert
PHP:
//$items: Array mit allen Fächer die Frei sind im Format Lager.Regal.Höhe.Fach
//Siehe Testdaten in der Nächsten Code-Box

//Notation:
//Lager.Regal.Höhe wird als 'adress' oder $adress verwendet
//Das Fach an sich, also der Letzte Part als $box

// Konstanten definire
define('C_NOT_SET',     -1);
define('C_END',         'END');

//$cases ist ein Array der pro adress die Boxen speichert
$cases = array();
// Fächer zerlegen und unter den Adress speichern
foreach($items as $index => $item){
    $parts = explode('.', $item);
    // Fach auslesen
    $box = array_pop($parts);
    // Adresse ' Lager ,Regal, Höhe' des Fachs extrahieren
    $adress = implode('.', $parts);
    // und in einen Array speichern
    $cases[$adress][$box] = $item;
}

$ranges = array();
foreach($cases as $adress => $boxes){
    // Fächer sortieren
    ksort($boxes, SORT_NUMERIC);
    
    // Ein End-Fach hinzufügen damit die Nachstehende Schleife auch den letzten Range abschliesst
    $boxes[] = C_END;
    // Varaiblen initialisieren    
    $lastBox = C_NOT_SET;
    $index = C_NOT_SET;
   
    foreach($boxes as $box => $item){
        if($box != $lastBox + 1 OR $item == C_END){
            // Alter Range beenden sofern bereits ein Range exisitiert oder wir am Ende angelangt sind
            if($index != C_NOT_SET){
                $ranges[$adress][$index]['last'] = $lastBox;
            }
            // Neuer Range beginnen ausser wir sind am Ende
            if($item != C_END){
                //Index um 1 erhöhen und neuer Range beginnen
                $ranges[$adress][++$index]['first'] = $box;
            }
        }
        // Box für den nächjsten durchgang speichern
        $lastBox = $box;
    }
}

print_r($ranges);
$ranges sieht dann so aus
PHP:
//Testdaten
$items = array(
        '1.1.1.1',
        '1.1.1.2',
        '1.1.1.3',
        '1.1.1.5',
        '1.1.1.6',
        '1.1.1.7',
        '1.1.1.9',
        '1.1.2.1',
        '1.1.2.2',
        '1.1.2.3',
        '1.5.1.5',
        '1.5.1.6',
        '1.6.1.1'
);
Code:
Array
(
    [1.1.1] => Array (
            [0] => Array (
                    [first] => 1
                    [last] => 3
                )
            [1] => Array (
                    [first] => 5
                    [last] => 7
                )

            [2] => Array (
                    [first] => 9
                    [last] => 9
                )
        )
    [1.1.2] => Array (
            [0] => Array (
                    [first] => 1
                    [last] => 3
                )
        )
    [1.5.1] => Array (
            [0] => Array (
                    [first] => 5
                    [last] => 6
                )
        )
    [1.6.1] => Array (
            [0] => Array (
                    [first] => 1
                    [last] => 1
                )
        )
)

Und so könnte eine Auswertung des Arrays $ranges aussehen
PHP:
// Mögliche Ausgabe
foreach($ranges as $adress => $ranges_1){
    foreach($ranges_1 as $range){
        if($range['first'] == $range['last']){
            // Es ist ein Einzel-Range
            echo sprintf('%s: Fach %s ist leer<br />', $adress, $range['first']);                    
        }else{
            //Es ist ein echter Range
            echo sprintf('%s: Fach %s-%s ist leer<br />', $adress, $range['first'], $range['last']);
        }
    }
}
Code:
1.1.1: Fach 1-3 ist leer
1.1.1: Fach 5-7 ist leer
1.1.1: Fach 9 ist leer
1.1.2: Fach 1-3 ist leer
1.5.1: Fach 5-6 ist leer
1.6.1: Fach 1 ist leer
 
Yaslaw, du hast natürlich recht. Ich wollte einfach nur schnell eine Lösung liefern. Und Thomas, ich habe meinen Code nicht getestet und von daher habe ich auch mögliche Denkfehler nicht ausgemerzt – nutze lieber die Lösung von Yaslaw.
 
Zuletzt bearbeitet:
Hallo,

Ich danke euch beiden für eure Antworten.

Nachdem ich den Code von Yaslaw verbaut und ausgiebig getestet habe, bin ich zu dem Entschluss gekommen, dass er zu 100% Funktioniert.

Vielen Dank
 

Neue Beiträge

Zurück