0

I have the following spreadsheet with source and destination data, ie someone could start their journey at source A, and end at destination D, the value returned will be '2'.

enter image description here

I need to recreate this in mysql, so far I have the following tables set up, how do I query this to produce the same format as the spreadsheet?



CREATE TABLE `locations` (
  `name` varchar(255) NOT NULL DEFAULT '',
  UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `zones` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `child_single` int(11) NOT NULL,
  `child_return` int(11) NOT NULL,
  `adult_single` int(11) NOT NULL,
  `adult_return` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

CREATE TABLE `locations_fares_lookup` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `outset` varchar(255) NOT NULL,
  `destination` varchar(255) NOT NULL,
  `zone` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `outset` (`outset`),
  KEY `destination` (`destination`),
  KEY `locations_fares_lookup_ibfk_3` (`zone`),
  CONSTRAINT `locations_fares_lookup_ibfk_1` FOREIGN KEY (`outset`) REFERENCES `locations` (`name`),
  CONSTRAINT `locations_fares_lookup_ibfk_2` FOREIGN KEY (`destination`) REFERENCES `locations` (`name`),
  CONSTRAINT `locations_fares_lookup_ibfk_3` FOREIGN KEY (`zone`) REFERENCES `zones` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

INSERT INTO `locations` (`name`)
VALUES
    ('A'),
    ('B'),
    ('C'),
    ('D'),
    ('E'),
    ('F');

INSERT INTO `zones` (`id`, `child_single`, `child_return`, `adult_single`, `adult_return`)
VALUES
    (1, 121, 111, 11, 12),
    (2, 120, 215, 240, 430),
    (3, 165, 260, 330, 520),
    (4, 205, 335, 410, 670),
    (5, 240, 385, 480, 770),
    (6, 122, 223, 224, 225),
    (7, 232, 323, 232, 222),
    (8, 222, 333, 33, 323);
etc...



INSERT INTO `locations_fares_lookup` (`outset`, `destination`, `zone`)
VALUES
    ('B', 'A', 2),
    ('C', 'A', 2),
    ('D', 'A', 2),
    ('E', 'A', 2),
    ('F', 'A', 5),
    ('A', 'B', 2),
    ('C', 'B', 2),
    ('D', 'B', 2),
    ('E', 'B', 2),
    ('F', 'B', 5);
etc...

https://www.db-fiddle.com/f/gSnEj5QwUBmku7UKnr8UaM/1

Apologies if this already has an answer, I have searched but I'm not sure what to search for.

6
  • and we need data and a dbfiddle example and of course what you have done till now Commented Feb 24, 2020 at 17:58
  • Yep, i will add these shortly, i'm going to put this question on hold until then Commented Feb 24, 2020 at 18:01
  • @nbk, I assume you downmarked this? have I provided enough info, or is there something else I'm missing/? Commented Feb 26, 2020 at 9:42
  • SO wants the data in text form and not only a dbfddle. Commented Feb 26, 2020 at 13:28
  • If you're building a spreadsheet for all data, why do you need anything more than SELECT * FROM *? And if that's your query, isn't your problem really with spreadsheet-generation? Commented Feb 26, 2020 at 15:50

1 Answer 1

1

You can use this to build your spreadsheet in another language

CREATE TABLE `locations` (
  `name` varchar(255) NOT NULL DEFAULT '',
  UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `zones` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `child_single` int(11) NOT NULL,
  `child_return` int(11) NOT NULL,
  `adult_single` int(11) NOT NULL,
  `adult_return` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

CREATE TABLE `locations_fares_lookup` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `outset` varchar(255) NOT NULL,
  `destination` varchar(255) NOT NULL,
  `zone` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `outset` (`outset`),
  KEY `destination` (`destination`),
  KEY `locations_fares_lookup_ibfk_3` (`zone`),
  CONSTRAINT `locations_fares_lookup_ibfk_1` FOREIGN KEY (`outset`) REFERENCES `locations` (`name`),
  CONSTRAINT `locations_fares_lookup_ibfk_2` FOREIGN KEY (`destination`) REFERENCES `locations` (`name`),
  CONSTRAINT `locations_fares_lookup_ibfk_3` FOREIGN KEY (`zone`) REFERENCES `zones` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

INSERT INTO `locations` (`name`)
VALUES
  ('A'),
  ('B'),
  ('C'),
  ('D'),
  ('E'),
  ('F');
  
INSERT INTO `zones` (`id`, `child_single`, `child_return`, `adult_single`, `adult_return`)
VALUES
  (1, 0, 0, 0, 0),
  (2, 120, 215, 240, 430),
  (3, 165, 260, 330, 520),
  (4, 205, 335, 410, 670),
  (5, 240, 385, 480, 770),
  (6, 0, 0, 0, 0),
  (7, 0, 0, 0, 0),
  (8, 0, 0, 0, 0);
  


INSERT INTO `locations_fares_lookup` (`outset`, `destination`, `zone`)
VALUES
  ('B', 'A', 2),
  ('C', 'A', 2),
  ('D', 'A', 2),
  ('E', 'A', 2),
  ('F', 'A', 5),
  ('A', 'B', 2),
  ('C', 'B', 2),
  ('D', 'B', 2),
  ('E', 'B', 2),
  ('F', 'B', 5);
✓

✓

✓

✓

✓

✓
SeLECT 
lo1.name,lo2.name
FROM locations lo1 CROSS JOIN locations lo2
name | name
:--- | :---
A    | A   
B    | A   
C    | A   
D    | A   
E    | A   
F    | A   
A    | B   
B    | B   
C    | B   
D    | B   
E    | B   
F    | B   
A    | C   
B    | C   
C    | C   
D    | C   
E    | C   
F    | C   
A    | D   
B    | D   
C    | D   
D    | D   
E    | D   
F    | D   
A    | E   
B    | E   
C    | E   
D    | E   
E    | E   
F    | E   
A    | F   
B    | F   
C    | F   
D    | F   
E    | F   
F    | F   
SELECT 
lo.lo1,
lo.lo2,
 l.zone
 FROM locations_fares_lookup l RIGHT JOIN
(SELECT lo1.name lo1,lo2.name lo2
FROM locations lo1 CROSS JOIN locations lo2) lo ON l.`outset` = lo.lo1 AND l.`destination` = lo.lo2
lo1 | lo2 | zone
:-- | :-- | ---:
A   | A   | null
B   | A   |    2
C   | A   |    2
D   | A   |    2
E   | A   |    2
F   | A   |    5
A   | B   |    2
B   | B   | null
C   | B   |    2
D   | B   |    2
E   | B   |    2
F   | B   |    5
A   | C   | null
B   | C   | null
C   | C   | null
D   | C   | null
E   | C   | null
F   | C   | null
A   | D   | null
B   | D   | null
C   | D   | null
D   | D   | null
E   | D   | null
F   | D   | null
A   | E   | null
B   | E   | null
C   | E   | null
D   | E   | null
E   | E   | null
F   | E   | null
A   | F   | null
B   | F   | null
C   | F   | null
D   | F   | null
E   | F   | null
F   | F   | null

db<>fiddle here

Or if you want a complete table use a stored procedure

DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `Findzone`()
BEGIN
    DECLARE finished INTEGER DEFAULT 0;
    DECLARE _name varchar(100) DEFAULT "";
    DECLARE _name1 varchar(100) DEFAULT "";
    DECLARE _firstrow SMALLINT DEFAULT  0;
    DECLARE _zone VARCHAR(5) DEFAULT  "";
    DECLARE _index INT DEFAULT  0;
    DECLARE _rowcount INT DEFAULT  0;
    
    DECLARE _CREATEQuery LONGTEXT DEFAULT "CREATE TEMPORARY TABLE Zonetable(Col0 varchar(100),";
    DECLARE _INSERTHEADERQuery LONGTEXT DEFAULT "INSERT INTO Zonetable VALUES('',";
    DECLARE _INSERTQuery LONGTEXT DEFAULT "INSERT INTO Zonetable VALUES ( ";
    -- declare cursor for stationname1
    DEClARE curstation 
        CURSOR FOR 
            SELECT name FROM locations ORDER BY name;
    -- declare cursor for stationname2
    DEClARE curstation1
        CURSOR FOR 
            SELECT name FROM locations ORDER BY name; 
    -- declare NOT FOUND handler
    DECLARE CONTINUE HANDLER 
        FOR NOT FOUND SET finished = 1;
 
DROP TABLE IF EXISTS Zonetable;
    SELECT count(*) INTO _rowcount
    FROM locations;

    OPEN curstation;
 
    getname1: LOOP
        FETCH curstation INTO _name;
        IF finished = 1 THEN 
            LEAVE getname1;
        END IF;
        SET _INSERTQuery = "INSERT INTO Zonetable VALUES ( ";
        SET _INSERTQuery = CONCAT(_INSERTQuery,'"',_name,'",');
        SET _index = 0;
        OPEN curstation1;
        getname2: LOOP
            FETCH curstation1 INTO _name1;
            IF finished = 1 THEN 
                SET finished = 0; 
                LEAVE getname2;
            END IF;
            SET _index = _index + 1;
            IF _firstrow = 0 then
                SET _CREATEQuery = CONCAT(_CREATEQuery,' COL',_index,' varchar(100)');
                SET _INSERTHEADERQuery = CONCAT(_INSERTHEADERQuery ,'"' ,_name1,'"');            
            END IF;
           IF EXiSTS(SELECT
                IF(l.zone IS NULL,'N/A',l.zone) zone
                FROM locations_fares_lookup l 
                WHERE l.`outset` = _name AND l.`destination` = _name1) then
                SELECT
                IF(l.zone IS NULL,'"N/A"',l.zone) zone INTO _zone
                FROM locations_fares_lookup l 
                WHERE l.`outset` = _name AND l.`destination` = _name1;
            ELSE
                SET _zone = 'N/A';
            END IF;
            IF _name = _name1 THEN
                SET _INSERTQuery = CONCAT(_INSERTQuery , '"N/A"');
            ELSE
                SET _INSERTQuery = CONCAT(_INSERTQuery ,'"',_zone,'"');
            END IF;
            IF _index < _rowcount THEN
                IF _firstrow = 0 then
                    SET _CREATEQuery = CONCAT(_CREATEQuery , ',');
                    SET _INSERTHEADERQuery = CONCAT(_INSERTHEADERQuery ,',');
                END IF;
                SET _INSERTQuery = CONCAT(_INSERTQuery , ',');
            END IF;
            
            
            
        END LOOP getname2;
        CLOSE curstation1;
        IF _firstrow = 0 then
            SET _CREATEQuery = CONCAT(_CREATEQuery , ');');
            SET @sql_query = _CREATEQuery;
            PREPARE stmt1 FROM @sql_query;
            EXECUTE stmt1;
            SET _INSERTHEADERQuery = CONCAT(_INSERTHEADERQuery , ');');
            SET @sql_query = _INSERTHEADERQuery;
            PREPARE stmt1 FROM @sql_query;
            EXECUTE stmt1;            
        END IF;
       SET _INSERTQuery = CONCAT(_INSERTQuery , ');');
        SET @sql_query = _INSERTQuery;
        PREPARE stmt1 FROM @sql_query;
        EXECUTE stmt1;
        SET _firstrow = 1;
    END LOOP getname1;
    CLOSE curstation;
    DEALLOCATE PREPARE stmt1;
    SELECT * FROM Zonetable;
    DROP TEMPORARY TABLE Zonetable;
END$$
DELIMITER ;

Which will give you following result with your database

procedure findzone

Sign up to request clarification or add additional context in comments.

1 Comment

It will be tricky to adept , but it avccept even big numbers of stations

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.