Compare commits

...

12 Commits

Author SHA1 Message Date
AdrienTriquet
c92b777e1c
Merge 15a39ca841 into 52c8427da7 2023-08-01 01:30:07 -03:00
Joe Germuska
52c8427da7 update for GA4 2023-06-26 16:53:32 -05:00
Joe Germuska
b696bcaf1b typo 2023-06-26 16:52:39 -05:00
adrien.triquet
15a39ca841 modification of an error about "" in po file. Note : it works even with those in a sentence. 2020-09-01 23:50:48 +02:00
adrien.triquet
1d745553cf Webpage ready to us in French 2020-09-01 23:46:22 +02:00
adrien.triquet
eb5218eaef Final translation in french, improvments and corrections 2020-09-01 23:44:44 +02:00
adrien.triquet
092abce19b improvment of the README.md 2020-06-10 00:40:40 +02:00
adrien.triquet
21ccac6c0f resolving a little mistale about membership_id in members 2020-06-09 19:51:12 +02:00
adrien.triquet
165cfd8fb6 realased version of all features : complete generation of the database in french and possibility to do it fastly in every language 2020-06-09 13:03:54 +02:00
adrien.triquet
ac1a2924c9 new version (new tables and modification of README) 2020-06-02 22:26:56 +02:00
adrien.triquet
72f3756fd4 README + improvements 2020-05-07 15:58:15 +02:00
adrien.triquet
7e9e2d90be draft of our internationalization work 2020-05-04 16:52:18 +02:00
29 changed files with 16862 additions and 23 deletions

View File

@ -57,18 +57,16 @@
<script>
window.onload = () => loadData('sql-murder-mystery.db');
</script>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-27829802-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-8F4WPDMPL5"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-27829802-1');
</script>
gtag('config', 'G-8F4WPDMPL5');
</script>
<title>The SQL Murder Mystery</title>
</head>
@ -291,4 +289,4 @@
</body>
</html>
</html>

View File

@ -0,0 +1,62 @@
SQL Murder Mystery in French
================================================================================
Authors : Adrien Triquet et Carla Danti, based on Knightlab's educational game : SQL Murder Mystery : https://mystery.knightlab.com/
--------------------------------------------------------------------------------
We are implementing a way to generate the database used in the game in French. It is coded as such as, if someone wants to implement their own translated version, they will have the pre existing structure to rely on.
--------------------------------------------------------------------------------
# data_base
The purpose is to generate a database in another language. For now, it is generating a french database. All the files are to be executed with Pyhton 3, as well as SQL Lite (a library used to implement SQL databases).
## How to create the database
Execute generation-python/__main.py__, the database will be created in data-base. You need to open it with a database manager (advice : open it with SQLiteStudio).
It appeals to each files for each class. There is a mother and a child class for each table.
### main.py explanation
The begining of the code is simply to work with the ORM, as it needs an engine to modify the database. Then, tables are constructed when the classes are called, and added to the database.
## data_base directory description :
- **generation_python** : all the files with the code, each file being an obect class, except for Base.py which is necessary to use the ORM, and main.py which is the file to execute to generate the database. See a simple class like interview, which is more commented, to understand how it works.
- **model_txt** : all the files needed to gather information for the database, that is to say the file we usein the code to translate some information (car makers we want to feature, car models, cities, ...)
- two png schemas for the databases, **schema_english.png** the official database schema given by Kinghtlab for the game, and **schema_french.png**, the french schema we made our code on.
## Principle of the code
We use the ORM (Object-Relational Mapping) SQLAlchemy for SQLite with Python to build the database.
All python class are linked. They generate the database table they have the name of. The first class is any given file is the parent class, with the table attributes, the relations between the tables, and some functions to fill in the tables.
The second class of the file is the child class, used to generate the french database. Some functions are redefined, as the attribute they build can be sepcific to French language or culture (for example the car plate number conventions are specific to different parts of the world).
In addition, they have the heritages to make them work with the ORM.
### model_txt
All files in this directory are used to fill in the databse.
“cities_list.txt” is a list of the 277 biggest French towns, based on a Wikipedia list.
“makers_list.txt” is a list of the 60 car brands most used in France.
“noise_text.txt” is the text of a novel : “Le mystère de la chambre jaune” by Gaston Leroux. It is provided by the Project Gutenberg and is free to use. We use this text to fill the crime descriptions in the table crime_scene_report.
"firstname_list.txt" is a list of the most commun firstnames in France based on a small part of a government free access database.
"lastname_list.txt" is a list of the most commun lastnames in France based on a small part of a government free access database.
"streetname_list.txt" is a list of name of streets in the city of Saint-Nazaire taken in part from https://sql.sh/2716-base-donnnees-rues-france according to their content policy.
--------------------------------------------------------------------------------
# translation_html
The purpose is to enable anyone without html skills to translate in is language.
We use gettext to generate a new html file with string of characters translated from the « walkthrough.html » file.
You can help translating in your language all the string of characters, they all are in « base.po ».
To generate the html, open « config », install python3 if needed. Then install packages needed and create .po and .mo following the instruction.
Then, in « translation.py », please modify all the « fr » according to your language.
Finally run the file. A « fr.hmtl » file is generated in « translation_html ».
You have to translate sentence after sentence. Unfortunately, some sentences are cut for gettext to work properly.
--------------------------------------------------------------------------------
### Licence :
Our work is under MIT License, based on Knightlab's educational game : SQL Murder Mystery
### Authors :
Carla Danti
Adrien Triquet
Both are Telecom SudParis students under the tutorship of Olivier Berger

View File

@ -0,0 +1,9 @@
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
engine = create_engine('sqlite:///../sql-murder-mystery-french.db')
Session = sessionmaker(bind=engine)
Base = declarative_base()

View File

@ -0,0 +1,119 @@
from sqlalchemy import Column, Integer, Text
from Base import Base, Session, engine
import random
Base.metadata.create_all(engine)
session = Session()
class CrimeSceneReport(Base):
__abstract__ = True
__tablename__ = 'crime_scene_reports'
#in order not to have an "id" column appearing in the database, we put all those columns as primary_keys
date = Column(Integer, primary_key=True)
type = Column(Text, primary_key=True)
description = Column(Text, primary_key=True)
city = Column(Text, primary_key=True)
def __init__(self, type_of_crime, date, city, description):
self.date = date
self.type = type_of_crime
self.description = description
self.city = city
""" Randomly attributes a date between start_year and end_year
Attributes : start_year, end_year (integers) """
def set_date(self, start_year, end_year):
year = random.randint(start_year, end_year)
month = random.randint(1, 12)
if month in [1, 3, 5, 7, 8, 10, 12]:
day = random.randint(1, 31)
if month == 2:
day = random.randint(1, 29)
else:
day = random.randint(1, 30)
if month < 10:
month = "0" + str(month)
if day < 10:
day = "0" + str(day)
c = str(year) + str(month) + str(day)
self.date = int(c)
""" Randomly attributes a description to the report
Arguments : path_file(char) : relative path leading to the file you want to use to set descriptions, must be in a
readable format
start(int) : number of the line where you want to begin picking up lines for description
end(int) : umber of the line where you want to end picking up the lines """""
def set_description(self, path_file, start, end):
# get the number of lines in the text to drown the clue in noise
file = open(path_file, "r")
n_lines = 0
line = file.readline()
while line:
n_lines += 1
line = file.readline()
file.close()
index = random.randint(start, n_lines - end)
file = open(path_file, "r")
description = file.readline()
count = 0
while count < index:
count += 1
description = file.readline()
file.close()
self.description = description
""" Randomly fills in the type of crime committed
Argument : types(list) : list of the type of crimes you want to put in the database """
def set_type(self, types):
index = random.randint(0, len(types)-1)
type_of_crime = types[index]
self.type = type_of_crime
""" Randomly selects a city on a given file (one city per line, and in a readable format)
Arguments : path_file : relative path to the list of cities """
def set_city(self, path_file):
# get the number of lines in the file
file = open(path_file, "r")
n_cities = 0
line = file.readline()
while line:
n_cities += 1
line = file.readline()
file.close()
index = random.randint(1, n_cities)
file = open(path_file, "r")
city = file.readline()
count = 0
while count < index:
count += 1
city = file.readline()
file.close()
self.city = city
class CrimeSceneReportFrench(CrimeSceneReport):
__tablename__ = 'rapports_scene_de_crime'
def __init__(self):
self.city = Column('ville', Text)
types = ["incendie criminel", "agression", "chantage", "corruption", "fraude", "meurtre", "braquage",
"contrebande", "vol"]
CrimeSceneReport.__init__(self, self.type, self.city, self.description, self.date)
self.set_date(2017, 2019)
self.set_description("../model_txt/noise_text.txt", 77, 369)
self.set_type(types)
self.set_city("../model_txt/cities_list.txt")

View File

@ -0,0 +1,133 @@
from sqlalchemy import Column, Integer, Text, ForeignKey
from sqlalchemy.orm import relationship
from Base import Base, Session, engine
import random
import string
Base.metadata.create_all(engine)
session = Session()
class DriversLicense(Base):
__abstract__ = True
#__tablename__ = 'drivers_licenses'
id = Column(Integer, primary_key=True)
age = Column('age', Integer)
height = Column('height', Integer)
eye_color = Column('eye_color', Text)
hair_color = Column('hair_color', Text)
gender = Column('gender', Text)
plate_number = Column('plate_number', Text)
car_make = Column('car_make', Text)
car_model = Column('car_model', Text)
def __init__(self, age, height, eye_color, hair_color, gender, plate_number, car_make, car_model):
self.age = age
self.height = height
self.eye_color = eye_color
self.hair_color = hair_color
self.gender = gender
self.plate_number = plate_number
self.car_make = car_make
self.car_model = car_model
""" Randomly fills in the age of the driver
Arguments : age_min, age_max (integers) """
def set_age(self, age_min, age_max):
self.age = random.randint(age_min, age_max)
""" Randomly fills in the height of the driver
Arguments : h_min, h_max (integers) """
def set_height(self, h_min, h_max):
self.height = random.randint(h_min, h_max)
""" Randomly fills in the eye color
Argument : eye_colors(list) """
def set_eye_color(self, eye_colors):
self.eye_color = random.choice(eye_colors)
""" Randomly fills in the hair color
Argument : hair_colors(list) """
def set_hair_color(self, hair_colors):
self.hair_color = random.choice(hair_colors)
""" Randomly fills in the gender of the driver
Argument : genders(list) """
def set_gender(self, genders):
self.gender = random.choice(genders)
""" Randomly fills in the car makers
Argument : car_makers(path_file) : path to the file with the list of car makers you want to feature (one maker
per line, and in a readable format) """
def set_car_make(self, car_makers):
file = open(car_makers, "r")
# get the number of lines in the file
n = 0
line = file.readline()
while line:
n += 1
line = file.readline()
file.close()
# get a random line to pick the car maker
index = random.randint(0, n-1)
file = open(car_makers, "r")
car_maker = file.readline()
count = 0
while count < index:
count += 1
car_maker = file.readline()
self.car_make = car_maker
""" Randomly fills in the car model
Argument : car_models(path_file) : path to the file with the list of car models you want to feature (one model
per line, and in a readable format) """
def set_car_model(self, car_models):
file = open(car_models, "r")
# get the number of lines in the file
n = 0
line = file.readline()
while line:
n += 1
line = file.readline()
file.close()
# get a random line to pick the car model
index = random.randint(0, n-1)
file = open(car_models, "r")
car_model = file.readline()
count = 0
while count < index:
count += 1
car_model = file.readline()
self.car_model = car_model
class DriversLicenseFrench(DriversLicense):
__tablename__ = 'permis_de_conduire'
def set_plate_number(self):
# making of plaque_number following French standards
l1 = random.choice(string.ascii_uppercase)
l2 = random.choice(string.ascii_uppercase)
m = random.randint(100, 999)
l3 = random.choice(string.ascii_uppercase)
l4 = random.choice(string.ascii_uppercase)
self.plate_number = l1 + l2 + "-" + str(m) + "-" + l3 + l4
def __init__(self):
eye_colors = ["noisette", "noir", "bleu", "marron", "vert"]
hair_colors = ["noir", "blond", "chatain", "gris", "blanc", "roux"]
genders = ["féminin", "masculin"]
DriversLicense.__init__(self, self.age, self.height, self.eye_color, self.hair_color, self.gender,
self.plate_number, self.car_make, self.car_model)
self.set_age(18, 90)
self.set_height(150, 200)
self.set_eye_color(eye_colors)
self.set_hair_color(hair_colors)
self.set_gender(genders)
self.set_plate_number()
self.set_car_make("../model_txt/makers_list.txt")
self.set_car_model("../model_txt/models_list.txt")

View File

@ -0,0 +1,82 @@
from Base import Base, Session, engine
from sqlalchemy.orm import relationship
from sqlalchemy import Column, Integer, Text, ForeignKey
import random
Base.metadata.create_all(engine)
session = Session()
class FacebookEventCheckIn(Base):
__abstract__ = True
#__tablename__ = 'facebook_events_checkins'
event_id = Column('event_id', Integer, primary_key=True, autoincrement=True)
event_name = Column('event_name', Text)
date = Column('date', Integer)
def __init__(self, event_name, date):
self.event_name = event_name
self.date = date
""" Randomly attributes an event_name to the report
Arguments : path_file(char) : relative path leading to the file you want to use to set descriptions, must be in
a readable format
start(int) : number of the line where you want to begin picking up lines for description
end(int) : umber of the line where you want to end picking up the lines """""
def set_event_name(self, path_file, start, end):
# get the number of lines in the text to hide the clues in the text
file = open(path_file, "r")
n_lines = 0
line = file.readline()
while line:
n_lines += 1
line = file.readline()
file.close()
index = random.randint(start, n_lines - end)
file = open(path_file, "r")
event_name = file.readline()
count = 0
while count < index:
count += 1
event_name = file.readline()
file.close()
self.event_name = event_name
""" Randomly attributes a date between start_year and end_year
Attributes : start_year, end_year (integers) """
def set_date(self, start_year, end_year):
year = random.randint(start_year, end_year)
month = random.randint(1, 12)
if month in [1, 3, 5, 7, 8, 10, 12]:
day = random.randint(1, 31)
if month == 2:
day = random.randint(1, 29)
else:
day = random.randint(1, 30)
if month < 10:
month = "0" + str(month)
if day < 10:
day = "0" + str(day)
c = str(year) + str(month) + str(day)
self.date = int(c)
class FacebookEventCheckInFrench(FacebookEventCheckIn):
__tablename__ = 'Evenement_Facebook'
person_id = Column(Integer, ForeignKey('personnes.id'))
person = relationship("PersonFrench")
def __init__(self, person):
FacebookEventCheckIn.__init__(self, self.event_name, self.date)
self.person = person
self.set_event_name("../model_txt/noise_text.txt", 77, 369)
self.set_date(2017, 2019)

View File

@ -0,0 +1,77 @@
from sqlalchemy import Column, Integer, Text, ForeignKey
from sqlalchemy.orm import relationship
from Base import Base, Session, engine
import random
import GetFitNowMembers
Base.metadata.create_all(engine)
session = Session()
class GetFitNowCheckIn(Base):
__abstract__ = True
#__tablename__ = 'get_fit_now_check_ins'
check_in_date = Column('check_in_date', Integer, primary_key=True)
check_in_time = Column('check_in_time', Integer, primary_key=True)
check_out_time = Column('check_out_time', Integer, primary_key=True)
def __init__(self, check_in_date, check_in_time, check_out_time):
self.check_in_date = check_in_date
self.check_in_time = check_in_time
self.check_out_time = check_out_time
""" Randomly attributes a date for the check_in between start_year and end_year
Attributes : start_year, end_year (integers) """
def set_check_in_date(self, start_year, end_year):
year = random.randint(start_year, end_year)
month = random.randint(1, 12)
if month in [1, 3, 5, 7, 8, 10, 12]:
day = random.randint(1, 31)
if month == 2:
day = random.randint(1, 29)
else:
day = random.randint(1, 30)
if month < 10:
month = "0" + str(month)
if day < 10:
day = "0" + str(day)
c = str(year) + str(month) + str(day)
self.check_in_date = int(c)
""" Randomly attributes a check-in and a check-out time """
def set_check_times(self):
# random check-in time
hour = random.randint(0, 23)
minute = random.randint(0, 59)
if hour < 10:
hour = "0" + str(hour)
if minute < 10:
minute = "0" + str(minute)
self.check_in_time = str(hour) + str(minute)
# random check-out time
hour = random.randint(0, 23)
minute = random.randint(0, 59)
if hour < 10:
hour = "0" + str(hour)
if minute < 10:
minute = "0" + str(minute)
self.check_out_time = str(hour) + str(minute)
class GetFitNowCheckInFrench(GetFitNowCheckIn):
__tablename__ = 'visites_que_du_muscle'
id_membre = Column(Text, ForeignKey('membres_que_du_muscle.id'))
membership = relationship("GetFitNowMemberFrench")
def __init__(self, membership):
GetFitNowCheckIn.__init__(self, self.check_in_date, self.check_in_time, self.check_out_time)
self.set_check_in_date(2017, 2019)
self.set_check_times()
self.membership = membership

View File

@ -0,0 +1,71 @@
from Base import Base, Session, engine
from sqlalchemy.orm import relationship
from sqlalchemy import Column, Integer, Text, ForeignKey
import random
import string
import Person
Base.metadata.create_all(engine)
session = Session()
class GetFitNowMember(Base):
__abstract__ = True
#__tablename__ = 'get_fit_now_members'
id = Column('id', Integer, primary_key=True)
membership_start_date = Column('membership_start_date', Integer)
membership_status = Column('membership_status', Text)
def __init__(self, membership_start_date, membership_status):
self.membership_start_date = membership_start_date
self.membership_status = membership_status
""" Randomly attributes a date between start_year and end_year
Attributes : start_year, end_year (integers) """
def set_membership_start_date(self, start_year, end_year):
year = random.randint(start_year, end_year)
month = random.randint(1, 12)
if month in [1, 3, 5, 7, 8, 10, 12]:
day = random.randint(1, 31)
if month == 2:
day = random.randint(1, 29)
else:
day = random.randint(1, 30)
if month < 10:
month = "0" + str(month)
if day < 10:
day = "0" + str(day)
c = str(year) + str(month) + str(day)
self.membership_start_date = int(c)
""" Randomly fills in the status of the membership
Argument : types(list) : list of the type of crimes you want to put in the database """
def set_membership_status(self, types):
index = random.randint(0, len(types) - 1)
membership_status = types[index]
self.membership_status = membership_status
class GetFitNowMemberFrench(GetFitNowMember):
__tablename__ = 'membres_que_du_muscle'
""" We need two 'person' to generate those two columns
to have the id corresponding to the name, you need to call twice the same 'person' in 'main' """
id_personne = Column(Integer, ForeignKey('personnes.id'))
person1 = relationship("PersonFrench", foreign_keys=[id_personne])
nom = Column(Text, ForeignKey('personnes.name'))
person2 = relationship("PersonFrench", foreign_keys=[nom])
def __init__(self, person1, person2):
status = ["normal", "or", "argent"]
GetFitNowMember.__init__(self, self.membership_start_date, self.membership_status)
self.set_membership_start_date(2015, 2017)
self.set_membership_status(status)
self.person1 = person1
self.person2 = person2

View File

@ -0,0 +1,69 @@
from sqlalchemy.sql.ddl import CreateSequence, DDL
from Base import Base, Session, engine
from sqlalchemy.orm import relationship
from sqlalchemy import Column, Integer, Text, ForeignKey, event
import random
Base.metadata.create_all(engine)
session = Session()
class Interview(Base):
#abstract enable us to choose a tablename in our own language in the child class
__abstract__ = True
""" the name if therefor not needed, however you can comment the '__abstract__ = True' to choose the tablename
direclty from the parent database """
#__tablename__ = 'interviews'
""" you need to change the names of the columns here for them to appear in your language
id is automaticly filed by the ORM as a primary key """
id = Column('id', Integer, primary_key=True)
transcript = Column('transcript', Text)
def __init__(self, transcript):
self.transcript = transcript
""" Randomly attributes a transcript to the report
Arguments : path_file(char) : relative path leading to the file you want to use to set descriptions, must be in a
readable format
start(int) : number of the line where you want to begin picking up lines for description
end(int) : umber of the line where you want to end picking up the lines """""
def set_transcript(self, path_file, start, end):
# get the number of lines in the text to drown the clue in noise
file = open(path_file, "r")
n_lines = 0
line = file.readline()
while line:
n_lines += 1
line = file.readline()
file.close()
index = random.randint(start, n_lines - end)
file = open(path_file, "r")
transcript = file.readline()
count = 0
while count < index:
count += 1
transcript = file.readline()
file.close()
self.transcript = transcript
#Child Class who heritates from interview, please create your own in your language
class InterviewFrench(Interview):
#tablename who is going to appear
__tablename__ = 'temoignages'
#Relationship with the class PersonFrench for the appearing column "person_id"
person_id = Column(Integer, ForeignKey('personnes.id'))
person = relationship("PersonFrench")
#init of the class, when you call it, you need to give as a parameter a person of class Person
def __init__(self, person):
#the initialisation is made with parameters of the parent class
Interview.__init__(self, self.transcript)
self.person = person
self.set_transcript("../model_txt/noise_text.txt", 77, 369)

View File

@ -0,0 +1,134 @@
from Base import Base, Session, engine
from sqlalchemy.orm import relationship
from sqlalchemy import Column, Integer, Text, ForeignKey
import random
import string
Base.metadata.create_all(engine)
session = Session()
class Person(Base):
__abstract__ = True
#__tablename__ = 'people'
id = Column(Integer, primary_key=True)
name = Column('name', Text)
address_number = Column('address_number', Integer)
address_street_name = Column('address_street_name', Text)
ssn = Column('ssn', Text)
def __init__(self, name, address_number, address_street_name, ssn):
self.name = name
self.address_number = address_number
self.address_street_name = address_street_name
self.ssn = ssn
""" Randomly fills in the name
Argument : firstNames(path_file) : path to the file with the list of names you want to feature (one name
per line, and in a readable format), same for lastNames"""
def set_name(self, firstnames, lastnames):
# get the number of lines in the first file
firstname_file = open(firstnames, "r")
n_firstname = 0
line = firstname_file.readline()
while line:
n_firstname += 1
line = firstname_file.readline()
firstname_file.close()
# get the number of lines in the first file
lastname_file = open(lastnames, "r")
n_lastname = 0
line = lastname_file.readline()
while line:
n_lastname += 1
line = lastname_file.readline()
lastname_file.close()
# get a random line to pick the names
index_first = random.randint(0, n_firstname - 1)
index_last = random.randint(0, n_lastname - 1)
firstname_file = open(firstnames, "r")
lastname_file = open(lastnames, "r")
firstname = firstname_file.readline()
lastname = lastname_file.readline()
count = 0
while count < index_first:
count += 1
firstname = firstname_file.readline()
while count < index_last:
count += 1
lastname = lastname_file.readline()
self.name = firstname + " " + lastname
""" Randomly attributes a number for the adress_number between 1 and 999 """
def set_adresse_number(self):
self.address_number = random.randint(1, 999)
""" Randomly fills in the name
Argument : street_name(path_file) : path to the file with the list of names you want to feature (one name
per line, and in a readable format) """
def set_address_street_name(self, path_file):
# get the number of lines in the file
file = open(path_file, "r")
n = 0
line = file.readline()
while line:
n += 1
line = file.readline()
file.close()
index = random.randint(1, n)
file = open(path_file, "r")
street_name = file.readline()
count = 0
while count < index:
count += 1
street_name = file.readline()
file.close()
self.address_street_name = street_name
""" Randomly generates a ssn following the French standards :
1st number : sex (0 for a man, 1 for a woman)
2nd and 3rd number : last two numbers of the birth year
4th and 5th : birth month
6th and 7th : department code in which the person is born
8th to 13th : random numbers"""
def set_ssn(self):
sex = random.randint(0, 1)
birth_year = random.randint(0, 99)
if birth_year < 10:
birth_year = "0" + str(birth_year)
birth_month = random.randint(1, 12)
if birth_month < 10:
birth_month = "0" + str(birth_month)
birth_place = random.randint(100, 999)
random_number = random.randint(100, 999)
string_ssn = str(sex) + str(birth_year) + str(birth_month) + str(birth_place) + str(random_number)
self.ssn = string_ssn
class PersonFrench(Person):
__tablename__ = 'personnes'
id_permis_de_conduire = Column(Integer, ForeignKey('permis_de_conduire.id'))
license = relationship("DriversLicenseFrench")
def __init__(self, license):
Person.__init__(self, self.name, self.address_number, self.address_street_name, self.ssn)
self.set_name("../model_txt/firstname_list.txt", "../model_txt/lastname_list.txt")
self.set_adresse_number()
self.set_address_street_name("../model_txt/streetnames_list.txt")
self.set_ssn()
self.license = license

View File

@ -0,0 +1,118 @@
# -*- coding: utf-8 -*-
# inserts the clues leading to the solution into the table
import sqlite3
import random
def fill_clues(nb_entries):
connexion = sqlite3.connect("../sql-murder-mystery-french.db")
cursor = connexion.cursor()
# create the report
type_of_crime = "meurtre"
date = 20190504
description = "Les caméras de surveillance montrent 2 témoins sur la scène du crime. Le premier habite la " \
"dernière maison de 'GENERAL DE GAULLE (Avenue du)'. Le deuxième témoin, nommée ROXANE, habite " \
"quelque part sur 'GAMBETTA (Boulevard)'."
city = "SQL Ville"
data = [date, type_of_crime, description, city]
cursor.execute('''INSERT INTO rapports_scene_de_crime(date, type, description, city) VALUES (?, ?, ?, ?)''', data)
# create the two witnesses
id_witness_1 = random.randint(0, nb_entries)
name = 'MARIUS DUBOIS'
address_number = 999
address_street_name = 'GENERAL DE GAULLE (Avenue du)'
ssn = 17406150424
data = (name, address_number, address_street_name, ssn, id_witness_1)
cursor.execute('''UPDATE personnes SET name = ?, address_number = ?, address_street_name = ?, ssn = ? WHERE
id = ? ''', data)
id_witness_2 = random.randint(0, nb_entries)
for id_witness_2 in [id_witness_1]:
id_witness_2 = random.randint(0, nb_entries)
name = 'ROXANE FAURE'
address_number = random.randint(1, 999)
address_street_name = 'GAMBETTA (Boulevard)'
ssn = '08406156524'
data = (name, address_number, address_street_name, ssn, id_witness_2)
cursor.execute('''UPDATE personnes SET name = ?, address_number = ?, address_street_name = ?, ssn = ? WHERE
id = ? ''', data)
# create the interviews for the two witnesses
transcript_1 = "J'ai entendu un coup de feu et j'ai vu un homme sortir en courant. Il avait un sac de sport 'Que " \
"du muscle'.. Je sais que seulement les membres 'or' ont ce sac. L'homme est ensuite monté dans une"\
" voiture avec la plate qui comprennait l'inscription 'LTD'"
data = (transcript_1, id_witness_1)
cursor.execute('''UPDATE temoignages SET transcript = ? WHERE person_id = ? ''', data)
transcript_2 = "J'ai vu le meurtre se dérouler, et j'ai reconnu le meurtrier : je l'ai vu au club de gym la " \
"semaine dernière, le 25 avril"
data = (transcript_2, id_witness_2)
cursor.execute('''UPDATE temoignages SET transcript = ? WHERE person_id = ? ''', data)
# create the member of the gym club (the suspect)
# in get_fit_now_checkin
id_suspect = random.randint(0, nb_entries)
for id_suspect in [id_witness_1, id_witness_2]:
id_suspect = random.randint(0, nb_entries)
date = '20190425'
data = (date, id_suspect)
cursor.execute('''UPDATE visites_que_du_muscle SET check_in_date = ? WHERE id_membre = ? ''', data)
# in get_fit_now_member
status = 'or'
data = (status, id_suspect)
cursor.execute('''UPDATE membres_que_du_muscle SET membership_status = ? WHERE id_personne = ? ''', data)
# in drivers_license
plate_number = 'LTD-619-DM'
gender = 'masculin'
data = (plate_number, gender, id_suspect)
cursor.execute('''UPDATE permis_de_conduire SET plate_number = ?, gender = ? WHERE id = ? ''', data)
# transcript of the suspect's interview
transcript_suspect = "J'ai été engagé par une femme. Je ne sais pas comment elle s'apelle, mais je sais qu'elle " \
"fait 165 ou 170 cm. Elle a les cheveux roux et conduit une Tesla Model S. Je sais aussi " \
"qu'elle est allée au Concert Philarmonique de SQL Ville 3 fois en Décembre 2017."
data = (transcript_suspect, id_suspect)
cursor.execute('''UPDATE temoignages SET transcript = ? WHERE person_id = ? ''', data)
# the partner's drivers license
id_partner = random.randint(0, nb_entries)
for id_partner in [id_witness_1, id_witness_2, id_suspect]:
id_partner = random.randint(0, nb_entries)
gender = 'féminin'
height = 165
hair_color = 'roux'
car_make = 'Tesla'
car_model = 'Model S'
data = (gender, height, hair_color, car_make, car_model, id_partner)
cursor.execute('''UPDATE permis_de_conduire SET gender = ?, height = ?, hair_color = ?, car_make = ?, car_model = ?
WHERE id = ? ''', data)
# facebook event check_in
event_name = 'Concert Philarmonique de SQL Ville'
event_ids = []
for i in range(3):
day = random.randint(1, 31)
date = '201712'+str(day)
event_id = random.randint(0, nb_entries)
for j in [event_ids]:
event_id = random.randint(0, nb_entries)
event_ids += [event_id]
data = (event_name, id_partner, date, event_id)
cursor.execute('''UPDATE Evenement_Facebook SET event_name = ?, person_id = ?, date = ? WHERE event_id = ? ''', data)
# person entry for the partner
partner_name = 'IRENE ADLER'
data = [partner_name, id_partner]
cursor.execute('''UPDATE personnes SET name = ? WHERE id = ?''', data)
connexion.commit()
connexion.close()

View File

@ -0,0 +1,77 @@
# -*- coding: utf-8 -*-
import random
from Base import Session, engine, Base
import os
from sqlalchemy.orm import query
from CrimeSceneReport import CrimeSceneReportFrench
from DriversLicense import DriversLicenseFrench
from GetFitNowCheckIn import GetFitNowCheckInFrench
from Person import PersonFrench
from Interview import InterviewFrench
from FacebookEventCheckIn import FacebookEventCheckInFrench
from GetFitNowMembers import GetFitNowMemberFrench
import Solution
# check if the database has already been generated
if os.path.exists('data_base/sql-murder-mystery-french.db'):
os.remove('data_base/sql-murder-mystery-french.db')
# generate database schema
Base.metadata.create_all(engine)
# create a new session
session = Session()
# number of values in the table
nb = 999
# create entries to persist in the database
for i in range(nb):
# create the tables in french
crime_scene_report = CrimeSceneReportFrench()
drivers_license = DriversLicenseFrench()
person = PersonFrench(drivers_license)
""" those following tables call a person as argument
each get_fit_now_members or interview will then be generated with the person created in the same loop
get_fit_now_members taked twice the same argument because it is needed for two columns """
get_fit_now_members = GetFitNowMemberFrench(person, person)
interview = InterviewFrench(person)
# add the tables to the database
session.add(crime_scene_report)
session.add(drivers_license)
session.add(person)
session.add(get_fit_now_members)
session.add(interview)
# Many to One : we make another loop because for them we need the rest of the database to be already filled
for i in range(nb):
#we take a random member in the existing database
rand1 = random.randrange(0, nb)
get_fit_now_member = session.query(GetFitNowMemberFrench)[rand1]
#we create a check_in for this member
get_fit_now_check_in = GetFitNowCheckInFrench(get_fit_now_member)
# we take a random person in the existing database
rand2 = random.randrange(0, nb)
person = session.query(PersonFrench)[rand2]
# we create a check_in for this person
facebook_event_check_in = FacebookEventCheckInFrench(person)
# add the tables to the database
session.add(facebook_event_check_in)
session.add(get_fit_now_check_in)
# commit and close session
session.commit()
session.close()
# insert the clues
Solution.fill_clues(nb)

View File

@ -0,0 +1,278 @@
Paris
Marseille
Lyon
Toulouse
Nice
Nantes
Montpellier
Strasbourg
Bordeaux
Lille13
Rennes
Reims
Saint-Étienne
Le Havre
Toulon
Grenoble
Dijon
Angers
Nîmes
Villeurbanne
Saint-Denis
Aix-en-Provence
Le Mans
Clermont-Ferrand
Brest
Tours
Amiens
Limoges
Annecy14
Perpignan
Boulogne-Billancourt
Metz
Besançon
Orléans
Saint-Denis
Argenteuil
Rouen
Mulhouse
Montreuil
Saint-Paul
Caen
Nancy
Tourcoing
Roubaix
Nanterre
Vitry-sur-Seine
Avignon
Créteil
Dunkerque16
Poitiers
Aubervilliers
Asnières-sur-Seine
Colombes
Versailles
Aulnay-sous-Bois
Saint-Pierre
Courbevoie
Fort-de-France
Cherbourg-en-Cotentin
Rueil-Malmaison
Champigny-sur-Marne
Le Tampon
Pau
Béziers
La Rochelle
Calais
Saint-Maur-des-Fossé
Antibes
Cannes
Mérignac
Drancy
Colmar
Saint-Nazaire
Ajaccio
Issy-les-Moulineaux
Évry-Courcouronnes
Noisy-le-Grand
Bourges
Vénissieux
La Seyne-sur-Mer
Cergy
Levallois-Perret
Quimper
Valence
Villeneuve-d'Ascq
Antony
Pessac
Clichy
Ivry-sur-Seine
Troyes
Cayenne
Neuilly-sur-Seine
Montauban
Tarn-et-Garonne
Chambéry
Niort
Sarcelles
Lorient
Beauvais
Le Blanc-Mesnil
Hyères
Saint-André
Épinay-sur-Seine
Villejuif
Pantin
Maisons-Alfort
Saint-Quentin
Meaux
Chelles
La Roche-sur-Yon
Cholet
Narbonne
Fontenay-sous-Bois
Saint-Louis
Vannes
Bondy
Fréjus
Arles
Sartrouville
Clamart
Bobigny
Corbeil-Essonnes
Sevran
Bayonne
Grasse
Massy
Cagnes-sur-Mer
Vincennes
Laval
Montrouge
Albi
Belfort
Évreux
Martigues
Suresnes
Vaulx-en-Velin
Brive-la-Gaillarde
Charleville-Mézières
Gennevilliers
Saint-Herblain
Saint-Malo
Carcassonne
Saint-Priest
Blois
Salon-de-Provence
Chalon-sur-Saône
Rosny-sous-Bois
Meudon
Aubagne
Saint-Brieuc
Châlons-en-Champagne
Bastia
Puteaux
Livry-Gargan
Choisy-le-Roi
Châteauroux
Saint-Germain-en-Laye
Mantes-la-Jolie
Alfortville
Saint-Laurent-du-Maroni
Valenciennes
Sète
Soisy-le-Sec
Les Sables-d'Olonne
Istres
Caluire-et-Cuire
Talence
Garges-lès-Gonesse
La Courneuve
Angoulême
Boulogne-sur-Mer
Le Cannet
Bourg-en-Bresse
Wattrelos
Castres
Thionville
Bron
Arras
Gap
Rezé
Tarbes
Compiègne
Melun
Le Lamentin
Draguignan
Alès
Bagneux
Douai
Stains
Marcq-en-Barœul
Gagny
Seine-Saint-Denis
Chartres
Anglet
Colomier
Périgueux
Montélimar
Saint-Martin-d'Hères
Pontault-Combault
Saint-Benoît
Saint-Joseph
Joué-lès-Tours
Villefranche-sur-Saône
Poissy
Châtillon
Villepinte
Savigny-sur-Orge
Montluçon
Franconville
Bagnolet
Sainte-Geneviève-des-Bois
Échirolles
Creil
Saint-Martin
Tremblay-en-France
Conflans-Sainte-Honorine
La Ciotat
Saint-Chamond
Saint-Raphaël
Thonon-les-Bains
Annemasse
Auxerre
Le Port
Neuilly-sur-Marne
Roanne
Haguenau
Palaiseau
Le Perreux-sur-Marne
Vitrolles
Saint-Leu
Athis-Mons
Marignane
Agen
Mâcon
Nevers
Nièvre
Romans-sur-Isère
Six-Fours-les-Plages
Sainte-Marie
Châtenay-Malabry
Meyzieu
Montigny-le-Bretonneux
La Possession
Villeneuve-Saint-Georges
Villenave-d'Ornon
Trappes
Cambrai
Les Mureaux
Matoury
Koungou
Châtellerault
Nogent-sur-Marne
Dumbéa
Schiltigheim
Houilles
Plaisir
Épinal
Le Chesnay-Rocquencourt
Vigneux-sur-Seine
L'Haÿ-les-Roses
Chatou
Dreux
Saint-Médard-en-Jalles
Goussainville
Liévin
Baie-Mahault
Pontoise
Lens
Viry-Châtillon
Rillieux-la-Pape
Charenton-le-Pont
Cachan
Saint-Cloud
Vandœuvre-lès-Nancy
Savigny-le-Temple
Villemomble
Malakoff
SQL Ville

View File

@ -0,0 +1,185 @@
GABRIEL
RAPHAËL
LÉO
LOUIS
EMMA
LUCAS
JADE
ADAM
LOUISE
ARTHUR
JULES
HUGO
ALICE
MAËL
LIAM
ETHAN
CHLOÉ
PAUL
NATHAN
GABIN
LÉA
SACHA
ROSE
NOAH
ANNA
MILA
TOM
INÈS
MOHAMED
AMBRE
JULIA
MIA
AARON
LÉNA
THÉO
MANON
JULIETTE
NOÉ
VICTOR
MARTIN
LOU
MATHIS
TIMÉO
ENZO
CAMILLE
ZOÉ
LOLA
AXEL
AGATHE
JEANNE
ANTOINE
LUCIE
LÉON
MARIUS
ROBIN
EVA
NINA
SARAH
ROMANE
VALENTIN
CHARLOTTE
CLÉMENT
BAPTISTE
RAYAN
TIAGO
LÉONIE
SAMUEL
AMIR
AUGUSTIN
NAËL
ROMY
ADÈLE
MAXIME
IRIS
LOUNA
SOFIA
MARGAUX
MAXENCE
GASPARD
LUNA
ELIOTT
ALEXANDRE
ISAAC
OLIVIA
CLÉMENCE
MATHÉO
YANIS
VICTORIA
EVAN
LÉANA
SIMON
CLARA
MALO
NINO
ELENA
VICTOIRE
KYLIAN
THOMAS
MARGOT
LENNY
GIULIA
CHARLIE
CAMILLE
LYAM
CAPUCINE
MATHILDE
IRENE
ANAÏS
LANA
OSCAR
LILOU
MILO
ALICIA
THÉA
GABRIELLE
LYA
NOA
YASMINE
MAËLYS
DIEGO
ISMAËL
LÉANDRE
APOLLINE
ELISE
ALIX
EMY
MATHYS
LISE
ALEXIS
ELSA
LORENZO
ESTEBAN
LILY
LISA
NOÉMIE
MARIE
WILLIAM
ROXANE
LYNA
ADRIEN
HÉLOÏSE
JEAN
DAVID
ALI
LOGAN
SANDRO
CANDICE
PABLO
VALENTINE
ANTONIN
JOSEPH
ZÉLIE
BENJAMIN
MAYA
AMINE
CÉLIA
MARIA
SOLINE
MAËLLE
CHARLES
LOUKA
MILAN
EMMY
ELIO
CHARLY
BASILE
ELÉNA
YOUNES
FAUSTINE
LILA
SALOMÉ
CONSTANCE
THIAGO
RAFAEL
LUCIEN
LAURA
MÉLINA
CHARLIE
TIMOTHÉE
AUGUSTE
MARIN
AMÉLIA
MALONE
OCÉANE
SARA

View File

@ -0,0 +1,999 @@
MARTIN
BERNARD
THOMAS
ROBERT
PETIT
DUBOIS
RICHARD
GARCIA
DURAND
LEFEBVRE
MOREAU
SIMON
LAURENT
LEROY
MICHEL
FONTAINE
DA SILVA
DAVID
MARTINEZ
MOREL
DUPONT
LAMBERT
FOURNIER
GIRARD
BERTRAND
LEFEVRE
ROUSSEAU
ROUX
VINCENT
FRANCOIS
BOYER
LEGRAND
ANDRE
MULLER
CHEVALIER
BONNET
GUERIN
LOPEZ
MERCIER
GARNIER
ADLER
SANCHEZ
HENRY
PEREZ
PEREIRA
FAURE
FERREIRA
ROBIN
CLEMENT
GAUTIER
GAUTHIER
PAYET
DUVAL
MORIN
BLANC
ROUSSEL
PERRIN
FERNANDEZ
NICOLAS
MASSON
RIVIERE
MARIE
LEMAIRE
NOEL
MATHIEU
DENIS
DOS SANTOS
LUCAS
MARCHAND
NGUYEN
DUMONT
DUFOUR
RODRIGUES
RENARD
JOLY
MEUNIER
CARON
FERNANDES
MEYER
RODRIGUEZ
BARBIER
BLANCHARD
GERARD
GONCALVES
LEROUX
SCHMITT
PIERRE
BRUNET
COLIN
LEMOINE
PICARD
ROGER
BRUN
GAILLARD
ROY
GIRAUD
OLIVIER
ARNAUD
VIDAL
AUBERT
ROCHE
LECLERCQ
GRONDIN
LECLERC
PHILIPPE
GONZALEZ
BOURGEOIS
MARTINS
LECOMTE
RENAUD
LOUIS
CARPENTIER
LACROIX
HOARAU
HUBERT
BENOIT
GUILLAUME
DUPUIS
FABRE
DUMAS
JEAN
VASSEUR
ROLLAND
DA COSTA
CHARLES
ADAM
GOMEZ
HUET
REY
BERTIN
GUILLOT
BERGER
PARIS
FLEURY
TRAORE
DIALLO
AUBRY
BOUCHER
ROYER
MAILLARD
LOPES
CAMARA
MENARD
JACQUET
MOULIN
GUYOT
POIRIER
CHARPENTIER
GOMES
DESCHAMPS
RIBEIRO
BARON
DUPUY
RENAULT
LEGER
COLLET
PREVOST
COUSIN
COHEN
LANGLOIS
CARRE
MAILLOT
SCHNEIDER
KLEIN
HERVE
HERNANDEZ
LEBRUN
GERMAIN
LE GALL
REMY
JULIEN
BOULANGER
POULAIN
LEBLANC
BOUVIER
ALVES
BAILLY
DANIEL
LEVEQUE
MILLET
BRETON
RUIZ
BENARD
MARQUES
MONNIER
BARRE
PELLETIER
LEMAITRE
PERROT
HOAREAU
JACOB
LE ROUX
MARECHAL
ETIENNE
MARCHAL
JOSEPH
ALEXANDRE
CHEVALLIER
BESSON
DELATTRE
GUICHARD
HAMON
TESSIER
CARLIER
LEBON
ANTOINE
DELAUNAY
MARTY
WEBER
COLLIN
MALLET
MICHAUD
LE GOFF
DE OLIVEIRA
GILLET
PERRIER
CORDIER
LEJEUNE
TEIXEIRA
CHAUVIN
PASQUIER
PERRET
DIJOUX
TRAN
DE SOUSA
HEBERT
HUMBERT
TURPIN
GIMENEZ
LESAGE
PINTO
BRIAND
NAVARRO
GEORGES
LEGROS
JACQUES
LAUNAY
LEBRETON
VOISIN
SAUVAGE
LEVY
LEDUC
PICHON
BESNARD
GILBERT
LELIEVRE
VALLEE
BIGOT
LAMY
PAUL
BOUCHET
PONS
CHARRIER
GUILLET
GAY
REYNAUD
ALBERT
BARBE
BLONDEL
TOURE
MARIN
MARTEL
OLLIVIER
BARTHELEMY
PINEAU
COSTA
HARDY
DIDIER
GUILLOU
LENOIR
EVRARD
FOFANA
VALENTIN
DEVAUX
GREGOIRE
SANTIAGO
CISSE
GAUDIN
COLAS
DIAS
BUISSON
MENDES
COURTOIS
MAHE
REGNIER
CAMUS
ALLARD
DUHAMEL
BEGUE
BERTHELOT
MORENO
GROS
BLANCHET
LAINE
RAYMOND
TECHER
WEISS
COULON
DESCAMPS
COULIBALY
LEFORT
JOUBERT
BODIN
VAILLANT
PASCAL
GUILLON
GUILBERT
LAPORTE
DELORME
MASSE
BAUDRY
CLERC
GODARD
MORVAN
DELAHAYE
TORRES
ROSSI
DIABY
LEGENDRE
TANGUY
VERDIER
MAURICE
RIOU
TOUSSAINT
BLIN
PRUVOST
COSTE
BONNEAU
COUTURIER
MARY
MARION
LECONTE
BOURDON
BRUNEAU
MAURY
THIBAULT
DIAZ
SEGUIN
LOMBARD
DELMAS
GILLES
FERRAND
RAYNAUD
BRUNEL
LAROCHE
MOHAMED
TEXIER
CHAUVET
LOISEAU
FISCHER
ALLAIN
BOUSQUET
DUPRE
LACOMBE
MAILLET
POTIER
AUGER
LEMONNIER
JOURDAN
GUIBERT
SYLLA
DRAME
MARTINEAU
PARENT
CHARTIER
GRENIER
NORMAND
BAZIN
LAGARDE
DIARRA
GUYON
CHRETIEN
POTTIER
BONNIN
JACQUOT
BLOT
PELTIER
GOSSELIN
MACE
DELANNOY
CHAUVEAU
ROCHER
FOUQUET
MONTEIRO
LY
PERON
BERNIER
FAIVRE
JOURDAIN
BOUVET
LABBE
VALLET
GALLET
IMBERT
HOFFMANN
STEPHAN
HAMEL
CADET
SALMON
NEVEU
WAGNER
PARMENTIER
SAMSON
CORTES
BOUTIN
DELAGE
BOULAY
BECKER
LECOQ
THIERRY
MAURIN
YILMAZ
MOREIRA
BAUER
PETITJEAN
JEANNE
FOUCHER
PAGES
CORNU
MUNOZ
ROUSSET
RAMOS
CORREIA
LEDOUX
FELIX
LEBLOND
LELEU
CASTEL
LETELLIER
LACOSTE
LAURET
PREVOT
BELLANGER
MERLE
HADDAD
DOUCET
DUCLOS
DUJARDIN
BOCQUET
LEON
VIAL
CLAIN
FAVRE
OLIVEIRA
SAIDI
GUY
BOULET
LALLEMAND
POISSON
VALETTE
DROUET
LEONARD
PICOT
PONCET
CHARBONNIER
LE CORRE
FERRE
MAIRE
RAULT
PIRES
CLAUDE
MARTINET
FORESTIER
ANDRIEU
BLONDEAU
ROSE
CARVALHO
BRAULT
MOUTON
BA
VIEIRA
CHATELAIN
KEITA
GIRAULT
LELONG
BONHOMME
FAVIER
ROSSIGNOL
THIEBAUT
GERVAIS
TELLIER
FLAMENT
GIL
MERLIN
FORTIN
BLAISE
LEFRANCOIS
SISSOKO
BILLARD
HUGUET
MENDY
DUCROCQ
PRIGENT
GUEGUEN
LEVASSEUR
BROSSARD
BENOIST
MARC
CHAPUIS
MAS
LAFON
COMTE
BARRET
PROVOST
LEPAGE
BAPTISTE
JOLLY
SERRE
GRANDJEAN
LABORDE
LE GUEN
GUILLEMOT
LE
MACHADO
BOURDIN
LE ROY
SOARES
GODEFROY
POMMIER
PAYEN
KELLER
LECOCQ
CORRE
BINET
GRAS
BOUQUET
FOULON
GRANGE
MAUREL
PAPIN
CHAMPION
GEOFFROY
THERY
VIVIER
MORAND
MARQUET
SAVARY
BATAILLE
SALAUN
BASSET
DUBREUIL
ESNAULT
SABATIER
BOUCHARD
CROS
DE ALMEIDA
LACOUR
BUREAU
CONSTANT
BESSE
DUMOULIN
BERTHIER
GICQUEL
SAUNIER
WINTERSTEIN
DORE
GRAND
GUILLEMIN
SAID
GRANGER
BRUNO
SCHMIDT
HUSSON
CARDON
CARTIER
MOUNIER
CHAMBON
JOUAN
SANTOS
LEBEAU
MILLOT
RICARD
FERRY
MAGNIER
TAVERNIER
GIBERT
LAVIGNE
POULET
JUNG
RIGAUD
SOLER
LAVAL
LERAY
KIEFFER
GONTHIER
WALTER
MIGNOT
JIMENEZ
LESUEUR
LEMARCHAND
JACQUEMIN
ARMAND
BEAUMONT
TOURNIER
LE BIHAN
COMBES
KONATE
CORNET
SELLIER
ZIMMERMANN
GODIN
GUILLARD
THIERY
AUBIN
LEFRANC
LEPRETRE
TERRIER
LEFEUVRE
JAMET
MANGIN
JOSSE
SILVA
DIOP
FERRER
ARNOULD
DELAPORTE
COCHET
ANDRIEUX
BONNARD
CARDOSO
PUJOL
FLORES
VIGNERON
LAMOTTE
BARREAU
GUITTON
CAILLAUD
FORT
MAYER
GABRIEL
PRAT
GUILBAUD
CREPIN
ROQUES
ANTUNES
DESHAYES
ROMAIN
ALI
MICHELET
WOLFF
SENECHAL
BERTHET
DIAKITE
GASSAMA
LECUYER
GOUJON
LE GAL
PRIEUR
SARRAZIN
ROUXEL
THEBAULT
OGER
BAILLEUL
LANG
DUCHENE
ROLAND
BAUDOUIN
QUERE
ALVAREZ
BAUDIN
BONIN
CHEVRIER
MAITRE
PIERRON
SOW
BON
GODET
LE BORGNE
SERRANO
DA CUNHA
GRIMAUD
KAYA
ARNOUX
BOIS
PROST
LAGRANGE
DUCHEMIN
BERARD
JOLIVET
GUIGNARD
NUNES
JULLIEN
AVRIL
MONTAGNE
SERRA
MONIER
SOULIER
VERNET
LOUVET
BARBOSA
SCHWARTZ
NIAKATE
TISSOT
VILLAIN
MAUGER
VACHER
DE CARVALHO
BASTIEN
SAHIN
GALLAND
GUEGAN
PARISOT
ROMERO
LASSERRE
PASQUET
BOURGUIGNON
DUARTE
YILDIZ
GOMIS
LAFONT
LASSALLE
SERGENT
THUILLIER
GROSJEAN
BOUCHE
SIDIBE
BEAUFILS
DUPIN
GEORGE
POLLET
RAGOT
TARDY
RENOU
RIO
TISON
BELIN
BROCHARD
VILLARD
LE BRIS
DUCHESNE
HAMELIN
BAYLE
CHOLLET
BONNEFOY
LENFANT
PEPIN
GARREAU
COUDERC
DAMOUR
SALOMON
GRANIER
RAMBAUD
LAFLEUR
LE FLOCH
LE MEUR
PAIN
COURTIN
DERRIEN
VANNIER
BOUTET
AUVRAY
COMBE
FAUCHER
BLANDIN
MORICE
LEBAS
MICHON
LECLERE
VARIN
AMAR
JACQUIN
BUREL
HUE
VERON
BRIERE
JANVIER
FERRARI
ROTH
SLIMANI
LANDAIS
BECK
CHOPIN
FOUCAULT
BOIVIN
DURET
BAUDET
MARAIS
TISSIER
AFONSO
MANCEAU
BABIN
HONORE
ALONSO
CANO
LAVERGNE
CHABOT
BERTHE
NICOLLE
CHRISTOPHE
DARRAS
JARRY
LE BERRE
MILLE
HERAULT
CHARLET
MESSAOUDI
VERGER
MAHIEU
PELLERIN
COELHO
LE BRAS
PAQUET
SY
MOLINA
BOUDET
CHEN
CELIK
LARCHER
MAGNE
LALANNE
BOREL
FOREST
KOCH
SIMONET
RIVET
BERTON
CHABERT
PINEL
PIQUET
CHARRON
ESTEVES
N'DIAYE
PERRON
GEFFROY
BOISSON
JAN
MARTEAU
PICHARD
JOUVE
BOUR
JAOUEN
SOULARD
BOISSEAU
DAHMANI
MONNET
RONDEAU
TISSERAND
CHOQUET
DIOT
SAUTRON
SICARD
LAMOUR
DELCROIX
PROUST
DELCOURT
PHAM
PORTIER
BISSON
YILDIRIM
BORDES
BONTEMPS
DEMBELE
LABAT
BOULARD
CHARLOT
ALIX
CARTON
LECERF
CAILLET
CONSTANTIN
DOUCOURE
DEVOS
GOBERT
MUNIER
CHERON
PASTOR
PORTE
BAUD
DELARUE
PELISSIER
TOUATI
FROMENT
MERLET
BOURGOIN
DIAWARA
PAILLARD
RENAUX
GOSSET
BARRY
CAPELLE
LHOMME
PRUDHOMME
SOUMARE
BOSSARD
SEGURA
JAMES
SAULNIER
DEMIR
MOINE
GILLOT
BESNIER
GAUBERT
JEAN-BAPTISTE
MANSOURI
CUVELIER
CHEMIN
DUBUS
MOUSSAOUI
GOURDON
RENAUDIN
SIMONIN
CHIRON
LOISEL
DROUIN
FERRIER
OUVRARD
ROUSSELLE
ABADIE
GROSS
ORTEGA
CASTRO
JARDIN
RIGAL
TOUTAIN
COLLARD
MALET
ZIEGLER
ASTIER
DUBOURG
MOHAMMAD
VERRIER
MONTEIL
BILLON
CLAUDEL
DOGAN
FAUVEL
LANGLET
POIROT
DAHAN
GASNIER
TEYSSIER
BACHELET
BEAUVAIS
METAYER
ABDALLAH
GUIRAUD
LE BRETON
CHATEAU
DELAMARE
DELHAYE
GOUPIL
HASSANI
FAYE
SALHI
ETHEVE
LOISON
NDIAYE
PAGE
QUENTIN
YANG
BOUILLON
CELLIER
CORMIER
SALLES
BAUDOIN
ABRAHAM
LANGLAIS
MUSSARD
RAYNAL
DEJEAN
MENAGER
VIAUD
MAES
THEVENIN
CONTE
CUNY
LEPRINCE
MICHAUX
LAPIERRE
LARUE
POUGET
THEVENET
BILLET
COUDERT
DURIEZ
FEVRIER
GENIN
RUSSO
CAILLE
BRESSON
DA CRUZ
PRUNIER
VIGIER
CARRERE
LEGAY
PIERROT
GONZALES
PUECH
DUBOS
FAYOLLE
LATOUR
LANDRY
FROGER
HAAS
HEMERY
FRITSCH
FUCHS
MOUSSA
BARDIN

View File

@ -0,0 +1,59 @@
Acura
Alfa-Romeo
Aston-Martin
Audi
Austin
Bentley
BMW
Bugatti
Cadillac
Chevrolet
Chrysler
Citroën
Dacia
Dodge
DS
Ferrari
FIAT
Ford
Ford-Mustang
Gumpert
Honda
Hummer
Hyundai
Infiniti
Iveco
Jaguar
Jeep
Kia
Lamborghini
Lancia
Land-Rover
Lexus
Maserati
Mazda
McLaren
Mercedes-Benz
Mia-electric
Mini
Mitsubishi
Nissan
Peugeot
Plymouth
Pontiac
Porsche
Renault
Rolls-Royce
Rover
Saab
Seat
Skoda
Smart
Subaru
Suzuki
Tesla Motors
Toyota
Venturi
Volkswagen
Volvo
Zenvo

View File

@ -0,0 +1,61 @@
Corolla
F-Series
Golf
Civic
Passat
Coccinelle
Escort
Accord
Hilux
Fiesta
Camry
Polo
Jetta
Model T
Focus
Impala
Serie 3
Classe E
Clio
Corsa
Grand Voyager
Astra
Elantra
Cutlass
Mustang
Land Cruiser
323
Uno
Punto
Taurus
2CV
Mdx
Mito
Vantage
A3
Maestro
Bentayaga
Chiron
Eldorado
Camaro
Sandero
Durango
Panda
Apollo
Kona
Q70
Daily
Renegade
Sportage
Urus
Delta
Lfa
Levante
Senna
Cooper
Scenic
Leon
Impreza
Octavia
Celerio
Model S

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,999 @@
GENERAL DE GAULLE (Avenue du)
BRIAND (Avenue Aristide)
KENNEDY (Avenue John )
MOKA (Avenue de)
PORTES CARTIER (Avenue des)
CLOS CADOT (Avenue du)
GAMBETTA (Boulevard)
SAINT MICHEL (Avenue)
CHATEAUBRIAND (Boulevard)
HEBERT (Boulevard)
REVEREND PERE UMBRICHT (Avenue du)
ROCHEBONNE (Digue de)
CHAPEL (Rue Claude)
RIANCOURT (Rue de)
MARTIN (Avenue Louis)
ABBE LORIN (Rue)
ALAUX (Impasse Gustave)
ARGENTEUIL (Rue d')
ATALANTE (Avenue)
BAZILLE (Impasse Frédéric)
BAZILLE (Rue Frédéric)
BELETTES (Rue des)
BLANCHE ROCHE (Rue de )
BLANDIN (Rue Etienne)
BOURG-CONDE (Impasse du)
CEZANNE (Rue Paul)
CHAGALL (Impasse Marc)
CHAMPS RICHARD (Rue des)
CHAPELET (Rue Roger)
COROT (Rue Camille)
CROIX RAUX (Rue de la)
DALI (Rue Salvador)
DE LA TOUR (Allée Georges)
DE VINCI (Rue Léonard)
DEGAS (Rue Edgar)
DOUANIER ROUSSEAU (Rue du)
EPHYRA (Allée)
GAUGUIN (Rue Paul)
GRAND VERGER (Rue du)
GUILLAUMIN (Rue Armand)
LAURENCIN (Rue Marie)
LEGUEN DE LACROIX (Rue François )
MARIN MARIE (Rue)
METIS (Allée)
MONET (Rue Claude)
MORISOT (Rue Berthe)
PERRINE (Rue de la)
PICASSO (Rue Pablo)
PISSARO (Rue Camille)
PUITS SAUVAGE (Rue du )
RENOIR (Rue Auguste)
SAINT-ETIENNE (Rue de )
SEURAT (Rue Georges)
SIGNAC (Rue Paul)
SISLEY (Rue Alfred)
TOULOUSE LAUTREC (Rue Henri de)
VAN GOGH (Allée Vincent)
CHEVALIER (Rue Adrien)
FOULQUES ( Passage des)
GARDES (Chemin des)
GOELETRIE (Impasse de la)
GOELETRIE (Rue de la)
HOUBARDERIE (Chemin de la)
PASSAGERE (Rue de la)
PETRELS (Chemin des)
PHILOSOPHES (Rue des)
POUPARDERIE (Chemin de la)
SAINT HELIER (Impasse)
TROCTIN (Rue de)
VAL RIANT (Chemin du)
ACHILLE (Rue de l')
ALCYON (Rue de l')
AMAZONE (Rue de l')
BALUE (Rue de la)
BARONNIE (Rue de la)
BASSE FLOURIE (Chemin de la)
BEAUGEARD (Rue Pierre)
BOULAIE (Chemin de la)
BOURNAY (Rue du)
BRIANTAIS (Allée de la)
BRISELAINE (Rue de)
CAPITAINE LESCOT (Impasse)
CAPITAINE LESCOT (Place)
CARAVANNIEZ (Rue)
CHALIBERT (Impasse)
CHESNAIE (Rue de la)
CLOS BRETON (Impasse du)
COETQUEN (Rue du)
COLAS (Square Henri)
COLLIN (Rue Eugène)
COUDRAY (Allée du)
CROIX BEAUGEARD (Rue de la)
DAGNET (Rue Amand)
DEJAN (Rue René)
DESGRES (Rue Gabriel)
DEVARIEUX (Rue Roger)
DIXMUDE (Rue de)
DOCTEUR CELESTIN HUET (Rue du)
DOUTRELEAU (Rue)
EGAULT (Rue Michel)
ENCLOS DU MOULIN (Rue de l')
ENFER (Rue de l')
EPINAY (Rue de l')
FLOURIE (Place de la)
FLOURIE (Rue de la)
GALIOTTE (Rue de la)
GENERAL PATTON (Rue du)
GENTILLERIE (Rue de la)
GODEST (Rue René)
GRAND DOMAINE (Allée du)
GROS CHENE (Impasse du)
GROS CHENE (Rue du)
GUIMERAIS (Rue des)
HAIZE (Rue Jules)
HAUTS MURS (Chemin des)
JOUANNY (Rue Isidore)
JOUVENTE (Impasse de)
LEONORE (Impasse de la)
LORETTE (Avenue de)
LORETTE (Impasse Hyacinthe)
LOTI (Rue Pierre)
LYS (Rue du)
MON PLAISIR (Allée de)
MONTADOR (Rue Jean-François)
NOGUES (Impasse Maurice)
NOGUES (Rue Maurice)
ORIEUX (Impasse des)
ORIEUX (Rue des)
PETITES LANDES (Rue des)
PONCEL (Place du)
RANCE (Boulevard de la)
RANCE (Passage de la)
RENCONTRE (Allée de la)
RONCES (Chemin des)
ROSAIS (Boulevard du)
TAVET (Rue Constant)
TERTRE VERRINE (Rue du)
TROIS CHENES (Allée des)
VAU GARNI (Chemin du)
VERDUN (Rue de)
VILLE JOUAN (Rue de la)
VILLE MENEE (Impasse de la)
AMITIE (Rue de l')
AURORE (Boulevard de l')
BEAUSEJOUR (Rue)
BISCAYENNE (Square de la)
BOISOUZE (Place)
BROUARD (Rue Eugène)
CALLO (Impasse Marcel)
CANCAVEN (Impasse)
CHAUSSEE (Rue de la)
CLARISSE (Rue de la)
CONFIANCE (Rue de la)
CROIX DES MARAIS (Rue de la)
DE COUBERTIN (Rue Pierre)
DORADE (Rue de la)
DUNANT (Boulevard Henry)
ESPADON (Boulevard de l')
GILLE (Rue Georges)
GRANDE ANGUILLE (Rue de la)
GREVES DE CHASLES (Rue des)
HERON (Impasse du)
HERON (Rue du)
JACQUES II (Rue)
LAENNEC (Rue)
LAMBETY (Impasse de)
LAMBETY (Place de)
LAMBETY (Rue de)
LECOUFLE (Rue)
MARAICHERS (Rue des)
MARE (Rue de la)
MARNE (Rue de la)
MONSIEUR VINCENT (Rue)
MONTAIGNE (Rue)
MOUCHOIR VERT (Rond-Point du)
MOULIN DE LA MOTTE (Impasse du)
OMNES (Allée René)
PARE (Rue Ambroise)
PERRIER (Boulevard)
PETITE ANGUILLE (Rue de la)
PIE (Rue de la)
PORTES ROUGES (Rue des)
QUATRE PAVILLONS (Rue des)
RENARD (Rue du)
REVENANT (Rue du)
ROCHER (Rue du)
SAUVAGE (Rond-Point)
TREHOUART (Boulevard)
VAL (Rue du)
VAYVA (Allée François)
VERGERS SAINTE-MARIE (Impasse des)
ALBERT 1er (Rue)
ALET (Rue d')
AMIRAL EPRON (Rue)
AMIRAL MAGON (Rue)
AMIRAL PROTET (Rue)
ARCHERS (Cour des)
ARONDEL (Rue)
BAS-SABLONS (Digue des)
BAS-SABLONS (Rue des)
BEL-AIR (Rue)
BIZEUX (Rue de)
BON PASTEUR (Cour du)
BOUGAINVILLE (Rue)
BOUVET (Place)
BUY (Allée Gaston)
CALVAIRIENNES (Passage des)
CERTAIN (Rue Pierre)
CHAPITRE (Rue du)
CHARCOT (Place)
CHEVREMONT (Rue)
CITE (Rue de la)
CLEMENCEAU (Rue Georges)
CLOS AGNES (Impasse)
CLOS JOLI (Rue du)
COCHET (Rue Jean-Marie)
COIN A L'AIR
COMMANDANT BOURDAIS (Passage du)
COMMANDANT DUBOSQ (Rue du)
COMMANDANT Y. MENGUY (Esplanade)
CONSTANTINE (Rue)
CORBIERES (Impasse des)
CORBINIERE (Passage de la)
CORBINIERE (Rue de la)
CORDERIE (Chemin de la)
DANYCAN (Rue)
DAUPHINE (Rue)
DICK (Rue du)
DOCTEUR PAUL BOULOGNE (Rue du)
DOUVILLE (Boulevard)
DREUX (Rue)
DUPERRE (Rue)
DUPORT DUTERTRE (Rue)
DURAND (Rue Mathieu)
ECHOS (Passage des)
EQUERRE (Rue de l')
ETOUPE (Rue de l')
FONTAINE (Rue de la)
FOUR (Rue du)
FOURS A CHAUX (Rue des)
GASPE (Rue de)
GENIE (Rue du)
GEORGE V (Rue)
GLACIS (Rue des)
GLORIOUX (Impasse du)
GLORIOUX (Rue du)
GODARD (Rue)
GOUAZON (Boulevard)
GOUYON (Rue de)
GUIBERT (Rue)
HAUTS-SABLONS (Rue des)
JARDINS DE SAINTE-ANNE (Allée des)
JEAN XXIII (Rue)
JUGAN (Rue Jeanne)
LAMORT (Rue Ernest)
LE FER (Rue)
LE POMELLEC (Rue)
LE TURC (Rue)
MARCHES (Rue des)
MARECHAL FOCH (Place du)
MARECHAL LECLERC (Place du)
MAREGRAPHE (Allée du)
MARINE (Impasse de la)
MARTINEAU (Rue René)
MESLE (Rue)
MONSEIGNEUR DUCHESNE (Impasse)
MONSEIGNEUR DUCHESNE (Place)
MONSEIGNEUR JUHEL (Place)
MONTRE (Rue de la)
NATION (Rue de la)
NAYE (Fort du)
NAYE (Quai du)
NAYE (Rue du)
NAYE (Terre-Plein du)
OLLIVRAULT (Impasse)
PICPUS (Jardin de)
PILOTE HEDOUIN (Rue du)
POIDS PUBLIC (Passage du)
POREE (Boulevard)
PORT (Rue du)
PRE BRECEL (Rue du)
REGARDS (Rue des)
RIVIERE (Cour)
ROBINOT (Passage)
ROSERAIE (Impasse de la)
ROULAIS (Place de la)
SABLONS (Rotonde des)
SAINT PERE (Cale)
SAINT PIERRE (Place)
SAINT PIERRE (Rue)
SEBASTOPOL (Quai)
SERVANNAIS (Terre Plein des)
SIAM (Rue de)
SOLIDOR (Quai)
TERRE NEUVE (Rue de)
TRICHET (Quai de)
TRICHET (Rue de)
VAL (Quai du)
VAL ANTIQUE (Impasse du)
VALLEE (Cour de la)
VARANGOT (Rue)
VILLE COLLET (Cour)
VILLE PEPIN (Rue)
ABREUVOIR (Rue de l')
ANCIENS COMBATTANTS (R.P.)
ANDROMEDE (Impasse d')
APPOLINE (Rue)
BASSIERES (Allée des)
BASSIN (Allée du)
BELIER (Rue du)
BELLEVUE (Impasse de)
BELLEVUE (Rue de)
BISON (Square du)
BOIS DEBOUT (Rue des)
BOSQUET AUX POMMES (Rue du)
CAMUS (Rue Albert)
CAPRICORNE (Rue du)
CASSIN (R.P. René) - DROIT DE L'HOMME - 1948 - 1998
CHAMP PEGASE (Ruelle du)
CHAPEL (Impasse Claude)
COMPTOIRS (Avenue des)
COTEAU (Impasse du)
COURTIL (Rue du)
DEMALVILAIN (Boulevard Léonce)
DESCARTES (Rue)
DUPARQUIER (Rue)
EOLE (Impasse d')
FEE MELUSINE (Rue de la)
FEE MORGANE (Rue de la)
FEE VIVIANE (Rue de la)
FLAUDAIS (Avenue de la)
FLAUDAIS (Allée de la)
FLORE (Rue de)
FONTAINE DE JOUVENCE (Rue de la)
FREMUR (Square du)
GEMEAUX (Rue des)
GRANDE MOINERIE (Rue de la)
GRASSINAIS (Allée de la)
GRASSINAIS (Rue de la)
GRIZZLY (Square du)
HAUT-PUITS (Rue du)
HAUTE FUTAIE (Impasse de la)
HULOTAIS (Rue de la)
HURE (Place de la)
HUS (Rue Jean)
ICARE (impasse d')
JUPITER (Rue de)
LAUNAY BRETON (Avenue de)
LOTUS (Passage des)
LYNX (Rue du)
MAISON NEUVE (Rue de la )
MANOIR (Place du)
MIROIR AUX FEES (Avenue du)
MONSEIGNEUR DIES (Rue)
MONTJOIE (Rue)
MOUFLON (Square du)
NENUPHARS (Rue des)
NEPTUNE (Rue de)
NYMPHES (Rue des)
OSERAIE (Impasse de l')
PENTHIEVRE (Square de)
PETIT CLOS (Passage du)
PETITE PATURE (Rue de la)
PEUPLERAIE (Impasse de la)
PIECE D'EAU (Impasse de la)
POINTEL (Rue)
PONT QUI TREMBLE (Rue du)
RABINES (Impasse des)
RENDEZ-VOUS (Passage des)
ROSEAUX (Passage des)
SAGITTAIRE (Rue du)
SAINT EXUPERY (Rue Antoine de)
SATURNE (Rue de)
SAULAIE (Rue de la)
SAUT DE LOUP (Rue du)
SEMILLANTE (Allée de la)
SOURCE (Rue de la)
TAPIS VERT (Allée du)
TERTRE BELOT (Rue du)
TONNELLES (Rue des)
TREGOR (Rue du)
TREHERAIS (Rue de la)
TRIEUX (Square du)
TROIS JOURNAUX (Rue des)
VERSEAU (Allée du)
VIGIE (impasse de la)
AJONCS (Rue des)
AMARYLLIS (rue des)
ANEMONES(rue des)
BLEUETS (Rue des)
BOURELAIS (Impasse de la)
BOURELAIS (Rue de la)
BOUTONS D'OR (Rue des)
BREGEONS (Rue des)
CAPUCINES (Rue des)
CHENARD DE LA GIRAUDAIS (Rue)
CHEVREFEUILLES (Rue des)
CLOS BARON (Rue du)
CYCLAMENS (Rue des)
CYTISES (Impasse des)
DAHLIAS (Rue des)
DE LA CONDAMINE (Impasse)
DE LA CONDAMINE Rue)
FOUGERES (Rue des)
GENETS (Rue des)
GRAND JARDIN (Impasse du)
GRAND JARDIN (Rue du)
GUYMAUVIERE (Rue de la)
HACHE (Rue de la)
IRIS (Rue des)
JACINTHES (Allée des)
JACINTHES (Rue des)
JANAIE (Rue de la)
LIERRES (Rue des)
LILAS (Rue des)
MAURIERS (Rue des)
MONNERAIE (Rue de la)
MOTTAIS (Rue du)
MYOSOTIS (Rue du)
NARCISSES (Rue des)
ONFROY (Rue Guillaume)
ORCHIDEES (Rue des)
PETITE BARONNIE (Chemin de la)
PETITE BARONNIE ( Impasse)
PETITS BOIS (Rue des)
PETITS CHAMPS (Rue des)
PRIMEVERES (Rue des)
ROUGERIES (Rue des)
RUETTE AU LOUP (Rue de la)
SPHINX (Allée du)
VILLE-ES-COURS (Rue de la)
VILLE-ES-HOUX (Rue de la)
VIOLETTES (Rue des)
ACADIENS (Rue des)
ALLENDE (Rue Salvador)
ANCIENS COMBATTANTS D'AFRIQUE DU NORD
ANTILLES (Rue des)
ARABIE (Rue de l')
ARGONNE (Rue de l')
ARKANSAS (Rue de l')
ARTOIS (Rue de l')
BARBOT (Rue Henri)
BARDELIERE (Rue Michel de la)
BOIS AURANT (rue du)
BOIS HERVEAU Rue DU
CAP (Enclos du)
CARAIBES (Square des)
CARIBOU (Rue du)
CASTOR (Rue du)
CHILI (Rue du)
CLOS DU NOYER (Rue du)
CLOS VERT (Rue du)
CURAÇAO (Impasse du)
DE LA BARDELIERE (Rue Michel)
DE TRIQUERVILLE (Rue J.P.)
DESIRADE (Rue de la)
DUCLOS GUYOT (Place)
DUCLOS GUYOT (Rue)
ELAN (Rue de l')
ETRIER (Rue de l')
FEE DES GREVES (Rue de la)
FEVAL (Rue Paul)
FOUQUET (Rue)
GENERAL FERRIE (Avenue du)
GRAND PASSAGE (Rue du)
GRAND PORT (rue)
GUADELOUPE (Rue de la)
ILE CROZET (Square de l')
ISLET (Square de l')
LE GENTIL (Rue)
LEVANT (Rue du)
LOUISIANE (Jardin de la)
LOUTRE (Rue de la)
LOZIER (Rue du)
MARTINIQUE (Rue de la)
MARTRE (Rue de la)
MER DU SUD (Rue de la)
MOTTE (Rue de la)
PERE PAUL BOULAY (Place)
PEROU (Rue du)
PONANT (Rue du)
SAINT FIACRE (Rue)
SAINT FRANCOIS XAVIER (Place)
SAINT LAURENT (Rue du)
SALINES (Rue des)
SUIPPES (Rue de)
TRINIDAD Rue de la)
TRIQUERVILLE (Rue Jean Pierre de)
VILLES ALLIS (Rue des)
VOSGES (Rue des)
YSER (Rue de l')
ABBE HUCHET (Rue)
ABBE PIERRE LEROY (Rue)
ALBERT (Rue Charles)
ALGER (Rue d')
ALSACE (Rue d')
AMIRAL LEVERGER (Rue)
ANJOU (Rue de l')
ARROMANCHES (Rue d')
ASTROLABE (Rue de l')
BERT (Rue Paul)
BIR HAKEIM (Impasse)
BIZERTE (Rue de)
BOIS JOLI (Passage du)
BOTREL (Bd Théodore)
BOUSSINOT POMPHILY (Rue)
BOUVIER (Rue Nicolas)
BRETAGNE (Place Anne de )
CALFATS (Rue des)
COMPAGNIE DES INDES (Rue de la)
CONTI (Avenue Anita)
COQUELIN (Parking Jean)
DERVEAUX (Passage Daniel)
DISTILLERIE (Place de la)
DOCTEUR PAUL AUBRY (Allée du)
DUBREUIL (Rue François)
DUFRESNE (Rue Marion)
DUNKERQUE (Rue de)
FERRY (Rue Jules)
FOUR A TABAC (Rue du)
FOURE (Rue Charles)
GARNIER DU FOUGERAY (Quai)
GRANDE HERMINE (Place de la)
GRANDE HERMINE (Rue de la)
GROENLAND (Impasse du)
GROENLAND (Rue du)
HALLES (Place des)
HALLES (Rue des)
HAMON (Rue)
HOCHELAGA (Rue de)
HUNIERS (Rue des)
ISLANDE (Rue d')
JAURES (Avenue jean)
JOUANJAN (Rue)
LA CHAMBRE (Rue Charles)
LE GOBIEN (Rue)
LE GUEN (Rue Emmanuel)
LEBAN (Allée Max)
LEDUC (Allée Gérard)
LERAY (Passage Jean)
MACE (Rue Jean)
MAINE (Rue du)
MARVILLE (Avenue de)
MERMOZ (Rue Jean)
MIRIEL (Rue)
MONOD (rue Théodore)
MOULIN (Rue du)
ORAN (Rue d')
PAPIN (Rue)
PEGUY (Place Charles)
PETIT CHAMP (Square du)
PINCON (Square Ernest)
POITOU (Rue du)
RENAN (Rue Ernest)
REPUBLIQUE (Boulevard de la)
RIO DE JANEIRO (Rue de)
ROOSEVELT (Avenue Franklin)
ROUTHOUAN (Rue du)
ROUVRE (Rue du)
ROZE (Rue Julienne)
SAFFRAY (Rue Jules)
SAINT MLEUX (Rue des Frères)
SEMARD (Rue Pierre)
TALARDS (Boulevard des)
TERRE NEUVE (Quai de)
THEBAULT (Rue Alphonse)
THOMAS (Square Albert)
TOUR D'AUVERGNE (Boulevard de la)
TOURVILLE (Rue de)
TUNIS (Rue de)
VERON (Paul) et ACPG (Rond Point)
VIGUIER (Rue)
VILLEBOIS MAREUIL (Boulevard)
VILLEBOIS MAREUIL (Impasse)
YVELIN (Rue)
AIGUILLE (Impasse de l')
ALBATROS (Impasse des)
AMOUREUX (Chemin des)
BATAS (Rue Jean)
BELLE FONTAINE (Impasse de)
BELLE FONTAINE (Rue de)
BERNARD (Rue Claude)
BOLTZ (Rue René)
BOUCHER (Rue Hélène)
BRAILLE (Rue Louis)
BRINDJONC (Rue Emile)
BURGOT (Rue Yves)
CAPITAIN (Impasse René)
CAPITAIN (Rue René)
CHAPELLE (Rue de la)
CLAUDEL (Rue Marguerite)
COLONEL DEMOLINS (Boulevard du)
CORDONNERIE (Rue de la)
CORMORANS (Impasse des)
COTTAGES (Avenue des)
COURLIS (Impasse des)
CROIX DU CHENE (Rue de la)
DOCTEUR GUIOT (Impasse du)
ESPERANCE (Boulevard de l')
ESPERANCE (Impasse de l')
FONTAINE AU BONHOMME (Avenue de la)
FRESNEL (Rue Augustin)
GOUTTE (Rue de la)
GUENE (Rue Emile)
JOUAN (Rue Pierre)
LESENECHAL (Rue Emile)
LHOTE (Rue Emile)
MALOUINE (Rue de la)
MALOUINIERE (Impasse de la)
MAQUIS DE BROUALAN (Rue du)
MARIETTE (Impasse)
MONTAGNE Saint-Joseph (Rue de la)
MOUETTES (Rue des)
NOGUETTE (Rue)
PARENTHOINE (Rue Alfred)
PASQUET Amand (Rue)
PLUVIERS (Impasse des)
PRAIRIES (Rue des)
RENAULT (Rue Félicité)
ROCAILLES (Allée des)
SAINT ESNOUL (Rue de)
SAINT PIERRE ET MIQUELON (Avenue)
SALENGRO (Avenue Roger)
STERNES (Impasse des)
TERTRE AUX NEFLES (Rue du)
VAL SAINT-JOSEPH (Rue du)
ABBE POUSSIN (Rue de l')
ACACIAS (Rue des)
AURIGNY (Allée d')
AVISO (Allée de l')
BAILLIS (Rue des)
BALADINS (Rue des)
BANCHETS (Impasse des)
BAS DE L'ILE (Rue du)
BATELEURS (Rue des)
BEAUFILS (Impasse Armel)
BEAUFILS (Impasse Edouard)
BEGONIAS (Impasse des)
BIGNON (Chemin du)
BIGNON (Rue du)
BISQUINE (Allée de la)
BOULNAYE (Rue de la)
BRIGANTIN (Allée du)
BURON (Allée du)
CAMELIAS (Rue des)
CAMPION (Allée Germaine)
CARAVELLE (Impasse de la)
CEZEMBRE (Rue de)
CHASSE (Impasse Charles)
CHAUSEY (Rue de)
CHEVALIERS (Rue des)
COLETTE (Avenue)
COLONEL ARMAND (Rue du)
CONNETABLE (Place du)
CORVETTE (Allée de la)
CROIX AU FEVRE (Rue de la )
CROLANTE (Allée de la)
DAUPHIN (Rue du)
DAVIER (Rue du)
DE LA VILLE MARQUE (Impasse H.)
DEPORTES (Boulevard des)
DORIS (Rue du)
DU PAPEU (Rue Gesril)
ECHEVINS (Rue des)
ECREHOUS (Allée des)
ECUYERS (Rue des)
EGLISE (Place de l')
EHBIENS (Allée des)
ENCLOS DU VERGER (Rue de l')
ERABLES (Rue des)
FOLIGNE (Rue André)
FONTENELLES (Avenue des)
FREGATE (Allée de la)
GALION (Rue du)
GARNERAY (Rue Louis)
GERBAULT (Rue Alain)
GERMAIN (Rue Paul)
GOELETTE (Allée de la)
GRANDE COTIERE (Impasse de la)
GRANDS POINTUS (Rue des)
GUERNESEY (Rue de)
HAUMET (Allée du)
ILE AGOT (Allée de l')
ILE DE SERQ (Allée de l')
ILE HARBOUR (Allée de l')
ILLE-ET-VILAINE (Impasse d')
JERSEY (Rue de)
JONGLEURS (Rue des)
LE BERRE (Impasse Léon)
LE BRAZ (Rue Anatole)
LE GOFFIC (Rue Charles)
LE GUYADER (Impasse Frédéric)
LE MASSON (Square Jean )
LE ROY (Impasse Florian)
LEVY (Avenue du)
MAILLARD (Rue Ella)
MAILLET (Rue Georges)
MARAIS (Rue Elie)
MARSOUIN (Impasse du)
MARTIN (Rue André)
MEINGA (Allée du)
MENESTRELS (Rue des)
MENETRIERS (Rue des)
MERCIERE (Allée de)
METTE (Rue Roger)
MIMOSAS (Rue des)
MINQUIERS (Rue des)
MORSE (Impasse du)
NOROIT (Passage)
OEILLETS (Rue des)
PANIER FLEURI (Impasse du)
PANIER FLEURI (Rue du)
PARC (Rue du)
PEPINIERE (Impasse de la)
PERE YVON (Rue du)
PETIT PRE (Rue du)
PETITE HUPEE (Impasse de la)
PETUNIAS (Rue des)
PEUPLIERS (Rue des)
PHARE (Rue du)
PLACE (Ruelle de la)
PLISSON (Impasse Berthe)
PONT TOQUE (Rue du)
PREVOTS (Rue des)
PROFESSEUR FEREY (Rue du)
RIMPONIERE (Impasse de la)
ROCHEPIETTE (Impasse de)
RUSSY (Impasse de)
RUSSY (Rue de)
SAINT IDEUC (Rue de)
SENECHAUX (Rue des)
SERRES (Chemin des)
SERRES (Impasse des)
SERVANTINE (Allée de la)
SORBIERS (Rue des)
SOUVESTRE (Impasse Emile)
TALVAS (Allée du Pere André-Marie)
TAMARIS (Rue des)
TROIS PIERRES (Impasse des)
TROUBADOURS (Rue des)
TROUVERES (Rue des)
TULIPES (Rue des)
VIERGE DE GRACE (Rue de la)
VILLE AUDRAIN (Impasse de la)
VILLE MARQUE (Rue Hersart de la)
ABBAYE (Rue de l')
ABBE FOURE (Rue)
ARGONAUTES (Rue des)
ARTILLEURS (Rue des)
BAS CHEMIN (Rue du)
BASSE VILLE AU ROUX (Rue de la)
BEAUPRE (Rue de)
BENETIN (Rue du)
BIGNE (Rue de la)
CANADA (Place du)
CLOS POUCET (Rue du)
COMMANDANT L'HERMINIER (Rue du)
CORBIERE (Rue Tristan)
CYPRES (Rue des)
DOCTEUR CHRISTIAN PAUL (Rue du)
ETRILLES (Rue des)
FIL D'ARIANE (Rue du)
FOUERE (Rue Jules)
GALETS (Rue des)
GOELAND (Impasse du)
GOELAND (Rue du)
GRAVE-DUPONT (Place)
GREVE (Rue de la)
GREVE (Avenue de la)
GUIMORAIS (Avenue de la)
HAUTE VILLE AU ROUX (Rue de la )
HAVRE (Chemin du)
HAVRE (Rue du)
HINDRE (Rue du)
HIPPOCAMPE (Impasse de l')
ILE BESNARD (Impasse de l')
ILE DES LANDES (Impasse de l')
LETRUNS (Rue des)
LONGUE RAIE (Rue de la)
MAC DONALD STEWART (Rue David)
MINIHIC (Rue du)
MOUSSES (Rue des)
NATIERE (Rue de la)
NICET (Avenue du)
NOTRE-DAME DES FLOTS (Allée)
NOVICES (Rue des)
PATELLES (Rue des)
PETITS PORTS (Rue des)
PLEIN SOLEIL (Allée du)
POINTE (Avenue de la)
POINTE DU CHRIST (allée de la)
PORCARO (Allée des dames de)
ROCHE (Chemin de la)
ROCHE (Rue de la)
ROCHERS SCULPTES (Chemin des)
ROTHENEUF (Impasse de)
ROTHENEUF (Boulevard de)
SAINT LOUIS (Allée)
SAINT MICHEL DES SABLONS (Boulevard)
SAINTE MARIE (Avenue)
SALINETTE (Rue de la)
SOUVENIR (Impasse du)
TESSERIE (Avenue de la)
TESSERIE (Impasse de la)
TINTIAUX (Rue des)
TOISON D'OR (Rue de la)
TOUR DU BONHEUR (Rue de la)
VAL (Place du)
VARDE (Avenue de la)
VARDE (Impasse de la)
VIEUX BANC (Rue du)
ABLETTE (Impasse de l')
AMANDIERS (Allée des)
ARTIMON (Rue de l')
AUBEPINE (Rue de l')
AUBERT (Avenue Louis)
AULNES (Rue des)
BAINS (Rue des)
BALEINE
BANQUEREAU (impasse du)
BARRAULT (Rue Marie Laurent)
BAUDET (Rue Hyacinthe)
BEAULIEU (Rue de)
BEAULIEU (Ruelle de)
BEAULIEU (Impasse du Tertre de)
BEAULIEU (Vallée de)
BEAUSITE (Impasse)
BEAUSOLEIL (Allée)
BEAUVOIR (Impasse)
BELLEVENT (Rue de)
BERENGER (Rue Marie)
BERGERIE (Rue de la)
BON VENT (Impasse du)
BONNE ROCHE (Impasse)
BONNET FLAMAND (Rue du)
BONNEVILLE (Rue de)
BORDERIE (Avenue de la)
BOURNAZEL (Avenue de)
BRIAND (Place Aristide)
BRIANT (Avenue Théophile)
BROCELIANDE (Avenue de)
BROCHET (Impasse du )
BROUASSIN (Rue)
BUTTES (Impasse des)
BUTTES (Rue des)
BUZARDIERE (Route de la)
CARNOT (Rue)
CEINTE (Impasse)
CHARMILLES (Rue des)
CHENES (Rue des)
CHENU (Rue Paul)
CHOPIER (Rue Louis)
CINEMA (Impasse du)
CLOS DE MATIGNON (Allée du)
CLOS DE MATIGNON (Rue du)
CLOS NEUF (Rue Herbert)
COLOMB (Rue Christophe)
COMMANDANT L. BERNICOT (Rue du)
COQ HARDI (Impasse du)
CORNILLET (Impasse)
COUARDES (Chemin des)
COUARDES (Rue des)
COUDRAY (Place Georges)
COUDRIERS (Rue des)
CROIX CHEMIN (Rue de la)
CROIX DESILLES (Rue de la)
DELALANDE (Rue Jean)
DELASTELLE (Impasse)
DEROULEDE (Avenue Paul)
DOCTEUR ANNE NOURY (Avenue du)
DOCTEUR ANNE NOURY (Impasse du)
DOCTEUR JUMELAIS (Rue du)
DOCTEUR R. NICOLLEAU (Avenue du)
DRAKKAR (Rue du)
DUGUESCLIN (Avenue)
DUVEAU (Rue Louis)
ECOLES (Rue des)
EDOUARD VII (Rue)
EGLANTINES (Rue des)
ETANG (Rue de l')
EXCELSIOR (Avenue)
FLAUBERT (Impasse Gustave)
FLAUBERT (Rue Gustave)
FLEURS (Impasse des)
FLEURS (Rue des)
FONTAINE AU VAIS (Rue de la)
FONTAINE AUX LIEVRES (Chemin de la)
FONTAINE AUX PELERINS (Rue de la)
FONTAN (Rue Ange)
FORGET (Rue Albert)
FORTS (Impasse des)
FRANCAIS LIBRES (Rond-Point des)
FRESNE (Rue du)
FRESNEL (Impasse Augustin)
FRISTEL (Rue Amélie)
GAITE (Rue de la)
GARDELLE (Rue de la)
GARROS (Rue Roland)
GENERAL DE CASTELNAU (Rue du)
GRANDE RIVIERE (Rue de la)
GUILLEVIC (Rue)
HALNA (Rue Georges)
HAUTES FALAISES (Impasse des)
HEBERT (Impasse)
HEBERT (Rue)
HERPIN (Avenue Eugène)
HESRY (Rue Jacques)
IFS (Chemin des)
JARNOUEN DE VILLARTAY (Rue Guy)
JASMIN (Rue du)
JONQUILLES (Rue des)
JURA (Impasse du)
KENNEDY (Cour du Président John )
KENNEDY (Impasse du Président John )
LAMBERT (Rue Arthur)
LANDELLES (Route des)
LE POLOZEC (Rue Georges)
LECONTE (Avenue Sébastien Charles )
LEFORESTIER (Rue René)
LEGATELOIS (Rue Jean)
LEGAVRE (Rue Pierre)
LEMARIE (Rue Henri)
LEMORDANT (Rue Julien)
LEMPEREUR (Rue Léon)
LEROUX (Rue Isidore et Jean)
LIBERATION (Rond-Point de la)
LORRAINE (Avenue de)
LUCET (Rue de)
MADAME DES BAS-SABLONS (Rue)
MARAIS RABOT (Rue du)
MARCHE (Place du)
MARE LITRE (Rue de la)
MARECHAL JUIN (Avenue du)
MARETTES (Rue des)
MARGUERITE (Rue Jean)
MASSEVILLE (Impasse)
MASSUERE (Route de la)
MELEZE (Impasse du)
MER (Place de la)
MERISIERS (Rue des)
METZ (Rue de)
MONT-FLEURY (Rue du)
MONTE-CARLO (Avenue de)
MOULIN CASSE (Route du)
MOULIN DU GUE (Rue du)
MOULIN DU GUE (Impasse du)
NATTIER (Avenue)
NAVIGATEURS (Rue des)
NIELLES (Avenue des)
NOMINOE (Rue)
NORMANDS (Impasse des)
NORMANDS (Rue des)
NOUETTE (Rue de la)
OLINDA (Rue)
OLIVIERS (Chemin des)
PER JAKEZ HELIAS (Rue)
PERROQUET (Impasse du)
PETIT PARAMÉ (Place du)
PETIT PARAMÉ (Rue du)
PICOT DE CLOS RIVIERE (Rue)
PINS (Allée des)
PLAGE (Rue de la)
PLATIER (Impasse du)
PLESSIS (Rue du)
POINCARE (Place)
PONT-PINEL (Rue du)
PRESIDENT Robert Schuman (Rue du)
PREVET (Avenue Charles)
PRIEURE SAINT-DOMIN (Rue du)
PRUNIERS (Rue des)
RABELAIS (Rue)
RESISTANCE (Place de la)
REVEREND PERE LEBRET (Rue du)
RIVASSELOU (Allée de)
ROC AUX DOGUES (Impasse du)
ROCHEBONNE (Boulevard de)
ROCHEBONNE (Passage)
ROUSSE (Impasse de)
ROUSSE (Chemin de)
SAINT ROCH (Avenue)
SAPINS (Avenue des)
SAULES (Impasse des )
SAULES (Rue des)
SIMON (Avenue Jules)
SIX FRERES RUELLAN (Rue des)
TANNERIE (Rue de la)
TERTRE (Impasse du)
TIERCELIN (Rue Louis)
TILLEULS (Impasse des)
TREGASTEL (Impasse)
TROIS MATS (Chaussée des)
TROIS MATS (Impasse des)
TURPIN (Rue Paul)
VALLON (Rue du)
VIKINGS (Impasse des)
VILLE CHESNAIS (Rue de la)
BERTHAUT (Rue Léon)
BLAIZE de MAISONNEUVE (Avenue)
BRINDEJONC des MOULINAIS (Rue)

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

View File

@ -0,0 +1,469 @@
msgid ""
msgstr ""
msgid "Hello world"
msgstr ""
msgid "Can you find out whodunnit?"
msgstr ""
msgid "There's been a Murder in SQL City! The SQL Murder Mystery is designed to be both a self-directed lesson to"
msgstr ""
msgid "learn SQL concepts and commands and a fun game for experienced SQL users to solve an intriguing crime."
msgstr ""
msgid "Walkthrough for SQL Beginners"
msgstr ""
msgid "If you're comfortable with SQL, you can"
msgstr ""
msgid "skip these explanations"
msgstr ""
msgid "and put your skills to the test! Below we introduce some basic SQL concepts, and just enough detail to solve the murder. If you'd like a more complete introduction to SQL, try"
msgstr ""
msgid "Select Star SQL."
msgstr ""
msgid "A crime has taken place and the detective needs your help. The detective gave you the crime scene report, but you somehow lost it. You vaguely remember that the crime was a"
msgstr ""
msgid "murder"
msgstr ""
msgid "that occurred sometime on"
msgstr ""
msgid "Jan.15, 2018"
msgstr ""
msgid "and that it took place in"
msgstr ""
msgid "SQL City"
msgstr ""
msgid "Start by retrieving the corresponding crime scene report from the police departments database."
msgstr ""
msgid "All the clues to this mystery are buried in a huge database, and you need to use SQL to navigate through this vast network of information."
msgstr ""
msgid "Your first step to solving the mystery is to retrieve the corresponding crime scene report from the police departments database."
msgstr ""
msgid "Below we'll explain from a high level the commands you need to know;"
msgstr ""
msgid "whenever you are ready, you can start adapting the examples to create your own SQL commands in search of clues --"
msgstr ""
msgid "you can run any SQL in any of the code boxes, no matter what was in the box when you started."
msgstr ""
msgid "Some Definitions"
msgstr ""
msgid "What is SQL?"
msgstr ""
msgid "SQL, which stands for Structured Query Language, is a way to interact with relational databases and tables in a way that allows us humans to glean specific, meaningful information."
msgstr ""
msgid "Wait, what is a relational database?"
msgstr ""
msgid "There's no single definition for the word"
msgstr ""
msgid "database"
msgstr ""
msgid "In general, databases are systems for managing information."
msgstr ""
msgid "Databases can have varying amounts of structure imposed on the data."
msgstr ""
msgid "When the data is more structured, it can help people and computers work with the data more efficiently."
msgstr ""
msgid "Relational databases are probably the best known kind of database. At their heart, relational databases are made up of "
msgstr ""
msgid "tables"
msgstr ""
msgid ", which are a lot like spreadsheets. Each column in the table has a name and a data type (text, number, etc.), and each row in the table is a specific instance of whatever the table is 'about'."
msgstr ""
msgid "The 'relational' part comes with specific rules about how to connect data between different tables."
msgstr ""
msgid "What is an ERD ?"
msgstr ""
msgid "ERD, which stands for Entity Relationship Diagram, is a visual representation of the relationships among all relevant tables within a database."
msgstr ""
msgid "You can find the ERD for our SQL Murder Mystery database below."
msgstr ""
msgid "The diagram shows that each table has a name (top of the box, in bold), a list of column names (on the left) and their corresponding data types (on the right, in all caps)."
msgstr ""
msgid "There are also some gold key icons, blue arrow icons and gray arrows on the ERD."
msgstr ""
msgid "A gold key indicates that the column is the primary key of the corresponding table, and a blue arrow indicates that the column is the foreign key of the corresponding table."
msgstr ""
msgid "Primary Key:"
msgstr ""
msgid "a unique identifier for each row in a table."
msgstr ""
msgid "Foreign Key:"
msgstr ""
msgid "used to reference data in one table to those in another table."
msgstr ""
msgid "If two tables are related, the matching columns, i.e. the common identifiers of the two tables, are connected by a gray arrow in the diagram."
msgstr ""
msgid "Here is the ERD for our database:"
msgstr ""
msgid "What is a query?"
msgstr ""
msgid "If you were to look at the data in this database, you would see that the tables are huge!"
msgstr ""
msgid "There are so many data points; it simply isnt possible to go through the tables row by row to find the information we need. What are we supposed to do?"
msgstr ""
msgid "This is where queries come in. Queries are statements we construct to get data from the database. Queries read like natural English (for the most part)."
msgstr ""
msgid "Let's try a few queries against our database. For each of the boxes below, click the «run» to «execute» the query in the box."
msgstr ""
msgid "You can edit the queries right here on the page to explore further. (Note that SQL commands are not case-sensitive, but it's conventional to capitalize them for readability."
msgstr ""
msgid "You can also use new lines and white space as you like to format the command for readability."
msgstr ""
msgid "Most database systems require you to end a query with a semicolon (';') although the system for running them in this web page is more forgiving.)"
msgstr ""
msgid "What elements does a SQL query have ?"
msgstr ""
msgid "A SQL query can contain :"
msgstr ""
msgid "SQL keywords (like the SELECT and FROM above)"
msgstr ""
msgid "Column names (like the name column above)"
msgstr ""
msgid "Table names (like the person table above)"
msgstr ""
msgid "Wildcard characters (such as "
msgstr ""
msgid "Functions"
msgstr ""
msgid "Specific filtering criteria"
msgstr ""
msgid "SQL Keywords"
msgstr ""
msgid "SQL keywords are used to specify actions in your queries."
msgstr ""
msgid "SQL keywords are not case sensitive, but we suggest using all caps for SQL keywords so that you can easily set them apart from the rest of the query."
msgstr ""
msgid "Some frequently used keywords are :"
msgstr ""
msgid "SELECT allows us to grab data for specific columns from the database:"
msgstr ""
msgid "* (asterisk): it is used after SELECT to grab all columns from the table;"
msgstr ""
msgid "column_name(s): to select specific columns, put the names of the columns after SELECT and use commas to separate them."
msgstr ""
msgid "FROM allows us to specify which table(s) we care about; to select multiple tables, list the table names and use commas to separate them."
msgstr ""
msgid "(But until you learn the JOIN keyword, you may be surprised at what happens. That will come later.)"
msgstr ""
msgid "The WHERE clause in a query is used to filter results by specific criteria."
msgstr ""
msgid "Let's try some of these things."
msgstr ""
msgid "The AND keyword is used to string together multiple filtering criteria so that the filtered results meet each and every one of the criteria."
msgstr ""
msgid "(There's also an OR keyword, which returns rows that match any of the criteria.)"
msgstr ""
msgid "If you haven't found the right crime scene report yet, click \"show solution\" above, and replace the contents of the box with just the revealed command. (Leave out the initial "
msgstr ""
msgid "If you figured out the query that shows the single crime scene report instead of a few for the same city and type, then congratulations and disregard the word \"incorrect\". You'll know if you got it!"
msgstr ""
msgid "Wildcards and other functions for partial matches"
msgstr ""
msgid "Sometimes you only know part of the information you need."
msgstr ""
msgid "SQL can handle that. Special symbols that represent unknown characters are called \"wildcards,\" and SQL supports two. The most common is the"
msgstr ""
msgid "wildcard."
msgstr ""
msgid "When you place a"
msgstr ""
msgid "wildcard in a query string, the SQL system will return results that match the rest of the string exactly, and have anything (or nothing) where the wildcard is. For example,"
msgstr ""
msgid "matches"
msgstr ""
msgid "and"
msgstr ""
msgid "California"
msgstr ""
msgid "The other, less commonly used wildcard, is"
msgstr ""
msgid "This one means 'match the rest of the text, as long as there's exactly one character in exactly the position of the"
msgstr ""
msgid "no matter what it is. So,"
msgstr ""
msgid "would match"
msgstr ""
msgid " but not"
msgstr ""
msgid "or"
msgstr ""
msgid "Important:"
msgstr ""
msgid "When using wildcards, you don't use the"
msgstr ""
msgid "symbol; instead, you use"
msgstr ""
msgid "SQL also supports numeric comparisons like"
msgstr ""
msgid "(less than) and"
msgstr ""
msgid "(greater than). You can also use the keywords"
msgstr ""
msgid "and all of those work with words as well as numbers."
msgstr ""
msgid "We've mentioned that SQL commands are not case-sensitive, but"
msgstr ""
msgid "querie values for"
msgstr ""
msgid "are. Sometimes you don't know how the text is stored in the database. SQL provides a couple of functions which can smooth that out for you. They're called"
msgstr ""
msgid "and you can probably figure out what they do, especially if you explore in the box below."
msgstr ""
msgid "SQL Aggregate Functions"
msgstr ""
msgid "Sometimes the questions you want to ask arent as simple as finding the row of data that fits a set of criteria."
msgstr ""
msgid "You may want to ask more complex questions such as “Who is the oldest person?” or “Who is the shortest person?”"
msgstr ""
msgid "Aggregate functions"
msgstr ""
msgid "can help you answer these questions. In fact, you learned an aggregate function above,"
msgstr ""
msgid "How old is the oldest person with a drivers license? With a small amount of data, you might be able to just eyeball it, but there thousands of records in the "
msgstr ""
msgid "table."
msgstr ""
msgid "drivers_license"
msgstr ""
msgid "Try"
msgstr ""
msgid "if you want to know just how many!) You can't just look over that list to find the answer."
msgstr ""
msgid "Here are a few useful aggregate functions SQL provides:"
msgstr ""
msgid "finds the maximum value"
msgstr ""
msgid "finds the minimum value"
msgstr ""
msgid "calculates the sum of the specified column values"
msgstr ""
msgid "calculates the average of the specified column values"
msgstr ""
msgid "counts the number of specified column values"
msgstr ""
msgid "There's another way to find minimum and maximum values, while also seeing more of the data."
msgstr ""
msgid "You can control the sort order of results you get. It's really quite intuitive: just use"
msgstr ""
msgid "followed by a column name. It can be challenging when there's a lot of data!"
msgstr ""
msgid "(When people get serious about working with SQL, they use better tools than this web-based system!)"
msgstr ""
msgid "By default, ORDER BY goes in \"ascending\" (smallest to largest, or A to Z) order, but you can be specific with"
msgstr ""
msgid "for ascending, or you can reverse it with"
msgstr ""
msgid "By now, you know enough SQL to identify the two witnesses. Give it a try!"
msgstr ""
msgid "Making connections"
msgstr ""
msgid "Joining tables"
msgstr ""
msgid "Until now, weve been asking questions that can be answered by considering data from only a single table."
msgstr ""
msgid "But what if we need to ask more complex questions that simultaneously require data from two different tables?"
msgstr ""
msgid "Thats where JOIN comes in."
msgstr ""
msgid "More experienced SQL folks use a few different kinds of JOIN -- you may hear about INNER, OUTER, LEFT and RIGHT joins."
msgstr ""
msgid "Here, we'll just talk about the most common kind of JOIN, the INNER JOIN."
msgstr ""
msgid "Since it's common, you can leave out INNER in your SQL commands."
msgstr ""
msgid "The most common way to join tables is using primary key and foreign key columns."
msgstr ""
msgid "Refer back to the Entity Relationship Diagram (ERD) above if you don't remember what those are, or to see the key relationships between tables in our database."
msgstr ""
msgid "You can do joins on any columns, but the key columns are optimized for fast results."
msgstr ""
msgid "It is probably easier to show how joins work with our interactive SQL system than to write them."
msgstr ""
msgid "Sometimes you want to connect more than one table. SQL lets you join as many tables in a query as you like."
msgstr ""
msgid "Now that you know how to join tables, you should be able to find the interview transcripts for the two witnesses you identified before. Give it a try!"
msgstr ""
msgid "Go Get 'em!"
msgstr ""
msgid "Now you know enough SQL to solve the mystery. You'll need to read the ERD and make some reasonable assumptions, but there's no other syntax that you need!"
msgstr ""
msgid "Check your solution"
msgstr ""
msgid "Credits"
msgstr ""
msgid "The SQL Murder Mystery was created by"
msgstr ""
msgid "while they were Knight Lab fellows. See the"
msgstr ""
msgid "GitHub repository"
msgstr ""
msgid "for more information."
msgstr ""
msgid "Adapted and produced for the web by"
msgstr ""
msgid "This mystery was inspired by"
msgstr ""
msgid "a crime in the neighboring Terminal City."
msgstr ""
msgid "Web-based SQL is made possible by"
msgstr ""
msgid "SQL query custom web components created and released to the public domain by Zi Chong Kao, creator of"
msgstr ""
msgid "Select Star SQL."
msgstr ""
msgid "Detective illustration courtesy of"
msgstr ""

View File

@ -0,0 +1,27 @@
#We'll use the =pybabel-python3= utility to manage GNU Gettext compatible catalog files.
# On Debian, it is in =/usr/bin/pybabel-python3=
# On MacOS, it is pybabel
# installation of babel
# dpkg is a package manager,it is brew on mac, ...
# here we list the package, if nothing is found, please install
dpkg -L python3-babel
pip install Babel
# installation of jinja2
pip install Jinja2
# Creating the catalog hierarchy, change "en" according to the language like here
mkdir -p locale/en/LC_MESSAGES/
mkdir -p locale/fr/LC_MESSAGES/
mkdir -p locale/ch/LC_MESSAGES/
# Initializing .po translation files, change "ch" according to the language and the directory of "en.po" according to the name and directory of your translation file (.po)
cp locale/en/LC_MESSAGES/en.po locale/ch/LC_MESSAGES/ch.po
# Generating the .mo files, change "fr" according to the language
pybabel compile -D fr -l fr -d locale 2>&1
# Translating
python3 translation.py

View File

@ -0,0 +1,628 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="utf-8">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSS -->
<link rel="stylesheet" href="https://cloud.webtype.com/css/d4767ecb-457a-4677-8761-72f890add836.css" />
<link rel="stylesheet" href="https://cdn.knightlab.com/libs/orangeline/0.1.1/css/orangeline.min.css" />
<!-- /CSS -->
<!-- FAVICONS -->
<link rel="apple-touch-icon" sizes="180x180"
href="https://cdn.knightlab.com/libs/orangeline/0.1.1/assets/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png"
href="https://cdn.knightlab.com/libs/orangeline/0.1.1/assets/favicons/favicon-32x32.png" sizes="32x32">
<link rel="icon" type="image/png"
href="https://cdn.knightlab.com/libs/orangeline/0.1.1/assets/favicons/favicon-16x16.png" sizes="16x16">
<link rel="manifest" href="https://cdn.knightlab.com/libs/orangeline/0.1.1/assets/favicons/manifest.json">
<link rel="mask-icon" href="https://cdn.knightlab.com/libs/orangeline/0.1.1/assets/favicons/safari-pinned-tab.svg"
color="#5bbad5">
<meta name="theme-color" content="#ffffff">
<!-- /FAVICONS -->
<title>The SQL Murder Mystery: Detailed Walkthrough</title>
<!-- Meta -->
<meta name="keywords" content="SQL, databases, game, fun">
<meta name="description"
content="Use SQL queries to solve the murder mystery. Suitable for beginners or experienced SQL sleuths.">
<!-- /Meta -->
<!-- Open Graph -->
<meta property="og:type" content="website" />
<meta property="og:title" content="SQL Murder Mystery" />
<meta property="og:description"
content="Use SQL queries to solve the murder mystery. Suitable for beginners or experienced SQL sleuths." />
<meta property="og:image" content="http://mystery.knightlab.com/174092-clue-illustration.png" />
<meta property="og:url" content="http://mystery.knightlab.com/walkthrough.html" />
<meta property="og:site_name" content="Knight Lab's SQL Murder Mystery" />
<meta property="fb:app_id" content="2361935160801585" />
<!-- /Open Graph -->
<!-- Twitter Card -->
<meta name="twitter:title" content="Knight Lab's SQL Murder Mystery">
<meta name="twitter:description"
content="Use SQL queries to solve the murder mystery. Suitable for beginners or experienced SQL sleuths.">
<meta name="twitter:image" content="http://mystery.knightlab.com/174092-clue-illustration.png">
<meta name="twitter:site" content="@knightlab">
<!-- /Twitter Card -->
<link rel="stylesheet" href='https://codemirror.net/lib/codemirror.css'>
<link rel="stylesheet" href="css/main.css" />
<link rel="stylesheet" href="css/neat.css" />
<script src="https://unpkg.com/@webcomponents/custom-elements@1.2.0/custom-elements.min.js"></script>
<script src="scripts/codemirror.js"></script>
<script src="scripts/codemirrorsql.js"></script>
<script src="scripts/autorefresh.js"></script>
<script src="scripts/main.js"></script>
<script>
window.onload = () => loadData('sql-murder-mystery.db');
</script>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-27829802-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag('js', new Date());
gtag('config', 'UA-27829802-1');
</script>
<title>The SQL Murder Mystery</title>
</head>
<body>
<nav id="navbar-product-top" class="navbar navbar-dark">
<ul>
<li class="logo">
<a href="http://knightlab.com">
<img src="https://cdn.knightlab.com/libs/orangeline/0.1.1/assets/knightlab-dark.png" />
</a>
</li>
</ul>
<div class="nav-mobile-menu">
<button class="button-plain">
<span class="icon-menu"></span>
</button>
</div>
<ul class="nav-right navbar-nav">
<li><a class="button button-dark button-small-tablet button-active"
href="https://knightlab.northwestern.edu/projects/">Projects</a></li>
<li><a class="button button-dark button-small-tablet " href="https://studio.knightlab.com/">Studio</a></li>
<li><a class="button button-dark button-small-tablet " href="https://localnewsinitiative.northwestern.edu/">Local
News</a></li>
<li><a class="button button-dark button-small-tablet " href="https://knightlab.northwestern.edu/posts/">Posts</a>
</li>
<li><a class="button button-dark button-small-tablet "
href="https://knightlab.northwestern.edu/community/">Community</a></li>
</ul>
</nav>
<header class="header-product">
<h1 class="product-logo product-logo-large">
SQL Murder Mystery
</h1>
<h2 class="product-tagline">Trouvez le meurtrier !</h2>
</header>
<div class="container">
<div id="intro" class="grid">
<div class="grid-item">
<img src="174092-clue-illustration.png" class="img-rounded"
alt="A decorative illustration of a detective looking at an evidence board.">
<p>
Il y a eu un meurtre à SQL City! Le mystère de SQL Murder Mystery est conçu pour être à la fois une leçon autodirigée pour
apprendre les concepts et les commandes SQL et un jeu amusant pour les utilisateurs SQL expérimentés pour résoudre un crime intrigant.
</p>
</div>
</div>
<div class="grid">
<div class="grid-item">
<h2>Procédure pas à pas pour les débutants SQL</h2>
<p>
Si vous êtes à l'aise avec SQL, vous pouvez <a href="index.html#experienced">sauter ces explications</a>
et mettre vos compétences à l'épreuve! Ci-dessous, nous présentons quelques concepts SQL de base et juste assez de détails pour résoudre le meurtre. Si vous souhaitez une introduction plus complète à SQL, essayez de
<a href="https://selectstarsql.com/">sélectionnez Star SQL.</a>
</p>
</div>
</div>
<div class="grid">
<div class="grid-item">
<p>
Un crime a eu lieu et le détective a besoin de votre aide. Le détective vous a donné le rapport sur la scène du crime, mais vous l'avez perdu. Vous vous souvenez vaguement que le crime était un
<strong>meurtre</strong> qui s'est produit le <strong>15 Janvier 2018</strong>
et qu'il a eu lieu à <strong>SQL City</strong>.
Commencez par récupérer le rapport de la scène de crime correspondant dans la base de données du service de police.
</p>
<p>
Tous les indices de ce mystère sont enfouis dans une énorme base de données et vous devez utiliser SQL pour naviguer dans ce vaste réseau d'informations.
La première étape pour résoudre le mystère consiste à récupérer le rapport de scène de crime correspondant dans la base de données du service de police.
Ci-dessous, nou expliquons d'un point de vu haut niveau les commandes que vous devez connaître ;
dès que vous êtes prêt, vous pouvez commencer à adapter les exemples pour créer vos propres commandes SQL à la recherche d'indices,
vous pouvez exécuter n'importe quelle commande SQL dans n'importe laquelle des fenêtres de code, peu importe ce qui se trouvait dans la boîte lorsque vous avez commencé.
</p>
</div>
</div>
<div class="grid">
<div class="grid-item">
<h2>Quelques définitions</h2>
<h3>Qu'est-ce que le SQL?</h3>
<p>
SQL, qui signifie Structured Query Language, est un moyen d'interagir avec les bases de données relationnelles et les tables d'une manière qui permet à nous, humains, de glaner des informations spécifiques et significatives.
</p>
<h3>Attendez, qu'est-ce qu'une base de données relationnelle ?</h3>
<p>Il n'y a pas de définition unique pour le mot<em> base de données.</em>
En général, les bases de données sont des systèmes de gestion de l'information.
Les bases de données peuvent avoir des quantités variables de structure imposées aux données.
Lorsque les données sont plus structurées, cela peut aider les gens et les ordinateurs à travailler avec les données plus efficacement.
</p>
<p>Les bases de données relationnelles sont probablement le type de base de données le plus connu. Au fond, les bases de données relationnelles sont constituées de
<em>tables</em>
, qui ressemblent beaucoup à des feuilles de calcul. Chaque colonne du tableau a un nom et un type de données (texte, nombre, etc.), et chaque ligne du tableau est une instance spécifique de ce dont la table parle.
La partie 'relationnelle' est accompagnée de règles spécifiques sur la manière de connecter des données entre différentes tables.
</p>
<h3>Qu'est-ce qu'un ERD ?</h3>
<p>
ERD, qui signifie Entity Relationship Diagram, est une représentation visuelle des relations entre toutes les tables pertinentes d'une base de données.
Vous pouvez trouver l'ERD pour notre base de données SQL Murder Mystery ci-dessous.
Le diagramme montre que chaque table a un nom (en haut de la boîte, en gras), une liste de noms de colonnes (à gauche) et leurs types de données correspondants (à droite, en majuscules).
Il existe également des icônes de clés dorées, des icônes de flèche bleue et des flèches grises sur l'ERD.
Une clé dorée indique que la colonne est la clé primaire de la table correspondante et une flèche bleue indique que la colonne est la clé étrangère de la table correspondante.
<dl>
<dt>
Clef primaire :
</dt>
<dd>
un identifiant unique pour chaque ligne d'une table.
</dd>
<dt>
Clef étrangère :
</dt>
<dd>
utilisée pour référencer les données d'une table à celles d'une autre table.
</dd>
</dl>
Si deux tables sont liées, les colonnes correspondantes, c'est-à-dire les identifiants communs des deux tables, sont reliées par une flèche grise dans le diagramme.
</p>
<p>Voici l'ERD de notre base de données :
</p>
<img src="schema.png" width='1002' height='491'>
</div>
</div>
<div class="grid">
<div class="grid-item">
<h2>
Qu'est-ce qu'une requête ?
</h2>
<p>
Si vous regardiez les données de cette base de données, vous verriez que les tables sont énormes!
Il y a tellement de points de données qu'il nest tout simplement pas possible de parcourir les tableaux ligne par ligne pour trouver les informations dont nous avons besoin. Que sommes nous sensés faire?
</p>
<p>
C'est là qu'interviennent les requêtes. Les requêtes sont des instructions que nous construisons pour obtenir des données de la base de données. Les requêtes se lisent comme de l'anglais naturel (pour la plupart).
Essayons quelques requêtes sur notre base de données. Pour chacune des cases ci-dessous, cliquez sur «run» pour «exécuter» la requête dans la case.
Vous pouvez modifier les requêtes ici même sur la page pour explorer davantage. (Notez que les commandes SQL ne sont pas sensibles à la casse, mais il est conventionnel de les mettre en majuscule pour plus de lisibilité.
Vous pouvez également utiliser de nouvelles lignes et un espace blanc comme vous le souhaitez pour formater la commande pour plus de lisibilité.
La plupart des systèmes de base de données exigent que vous terminiez une requête par un point-virgule (';') bien que le système pour les exécuter dans cette page Web soit plus indulgent.)
</p>
<sql-exercise data-question="Just how many people are in this database?"
data-comment="Don't worry about exactly what this means, but know that you can change 'person' to any other table from the ERD to learn how many rows that table has. Try it!"
data-default-text="SELECT count(*)
FROM person;"></sql-exercise>
<sql-exercise data-question="What do we know about those people?"
data-comment="If you want all the data for each row in a table, use '*' after 'SELECT'. As you just learned, there are thousands of people, so rather than see all of them, we'll limit the results to just the first 10. Run this, then change the table name or limit number and see what happens."
data-default-text="SELECT * FROM person LIMIT 10;"></sql-exercise>
<sql-exercise data-question="What are possible values for a column?"
data-comment='When working with data, always see if you can find documentation that explains the database structure (like the ERD) and valid values. But sometimes thats not available. Here we show how the DISTINCT keyword can give you a quick look at which values are in the database. After you run it, delete the word DISTINCT and run it again. See the difference? (After you try that, you may want to click the "reset" button and run one more time before you continue.)'
data-default-text="SELECT DISTINCT type FROM crime_scene_report;"></sql-exercise>
</div>
</div>
<div class="grid">
<div class="grid-item">
<h3>Quels éléments contient une requête SQL ?</h3>
<p>Une requête SQL peut contenir :
<ul>
<li>Mots clés SQL (comme SELECT et FROM ci-dessus)</li>
<li>Noms de colonne (comme le nom de la colonne ci-dessus)</li>
<li>Noms de table (comme le tableau des personnes ci-dessus)</li>
<li>Caractères génériques (tels que <code>%</code>)</li>
<li>fonctions</li>
<li>Critères de filtrage spécifiques</li>
<li>Etc</li>
</ul>
</p>
<h4 id="sql-keywords">Mots clés SQL</h4>
<p>
Les mots clés SQL sont utilisés pour spécifier des actions dans vos requêtes.
Les mots clés SQL ne sont pas sensibles à la casse, mais nous vous suggérons d'utiliser toutes les majuscules pour les mots clés SQL afin que vous puissiez facilement les distinguer du reste de la requête.
Certains mots clés fréquemment utilisés sont :
</p>
<h5>SELECT</h5>
<p>SELECT nous permet de récupérer des données pour des colonnes spécifiques de la base de données :</p>
<ul>
<li>
* (astérisque) : il est utilisé après SELECT pour récupérer toutes les colonnes de la table ;
</li>
<li>
nom_colonne(s) : pour sélectionner des colonnes spécifiques, mettez les noms des colonnes après SELECT et utilisez des virgules pour les séparer.
</li>
</ul>
<h5>FROM</h5>
<p>FROM nous permet de spécifier la ou les tables qui nous intéressent; pour sélectionner plusieurs tables, listez les noms de tables et utilisez des virgules pour les séparer.
(Mais tant que vous n'aurez pas appris le mot clé JOIN, vous serez peut-être surpris de ce qui se passe. Cela viendra plus tard.</p>
<h5>WHERE</h5>
<p>La clause WHERE dans une requête est utilisée pour filtrer les résultats selon des critères spécifiques.</p>
<p>Essayons certaines de ces choses.</p>
<sql-exercise
data-question="Here's a simple query to get everything about a specific person. (Don't worry&mdash;all of the SSNs are made up.) "
data-comment="Note that you need to use single straight quotes (') around literal text so the database can tell it apart from table and column names. After you run it, try again with Yessenia Fossen, Ted Denfip or Davina Gangwer."
data-default-text="SELECT * FROM person WHERE name = 'Kinsey Erickson'"></sql-exercise>
<p>Le mot clé AND est utilisé pour enchaîner plusieurs critères de filtrage afin que les résultats filtrés répondent à chacun des critères.
(Il existe également un mot clé OR, qui renvoie les lignes qui correspondent à l'un des critères.)</p>
<sql-exercise data-question="This query only returns reports about a specific type of crime in a specific city."
data-comment=" Notice that when querying for text values, you must match the data as it is in the database. Try changing 'Chicago' to 'chicago' and running the statement. Then, see if you can edit this SQL statement to find the first clue based on the prompt above."
data-default-text="SELECT * FROM crime_scene_report
WHERE type = 'theft'
AND city = 'Chicago';" data-solution="SELECT * FROM crime_scene_report
WHERE type = 'murder'
AND city = 'SQL City';"></sql-exercise>
<p>Si vous n'avez pas encore trouvé le bon rapport de scène de crime, cliquez sur "Afficher la solution " ci-dessus et remplacez le contenu de la boîte par la commande révélée. (Oubliez l'initiale
<code>/*</code>)
Si vous avez trouvé la requête qui montre le rapport de scène de crime unique au lieu de quelques-uns pour la même ville et le même type, félicitations et ne tenez pas compte du mot «incorrect». Vous saurez si vous l'avez!
</p>
<h4 id='wildcards'>Caractères génériques et autres fonctions pour les correspondances partielles</h4>
<p>Parfois, vous ne connaissez qu'une partie des informations dont vous avez besoin.
SQL peut gérer cela. Les symboles spéciaux qui représentent des caractères inconnus sont appelés «caractères génériques» et SQL en prend en charge deux. Le plus courant est le
<code>%</code>
joker.</p>
<p>Lorsque vous placez un <code>%</code>
caractère générique dans une chaîne de requête, le système SQL retournera des résultats qui correspondent exactement au reste de la chaîne et contiendra n'importe quoi (ou rien) là où se trouve le caractère générique. Par exemple,
<code>'Ca%a'</code> correspondent <code>Canada</code> et <code>Californie</code>.</p>
<p>L'autre caractère générique, moins couramment utilisé, est <code>_</code>.
Celui-ci signifie `correspondre au reste du texte, tant qu'il y a exactement un caractère exactement à la position du
<code>_</code>, peu importe ce que c'est. Alors,
<code>'B_b'</code> correspondrait<code>'Bob'</code> et <code>'Bub'</code> mais pas <code>'Babe'</code>ou
<code>'Bb'</code>.</p>
<p><strong>Important :</strong> Lorsque vous utilisez des caractères génériques, vous n'utilisez pas le <code>=</code> symbole; à la place, vous utilisez
<code>LIKE</code>.
</p>
<sql-exercise data-question="Try out some wildcards."
data-comment="Once you run this command, try variations like 'Irvin_' and 'I%e' -- and then explore some more."
data-default-text="SELECT DISTINCT city
FROM crime_scene_report
WHERE city LIKE 'I%';"></sql-exercise>
<p>SQL prend également en charge les comparaisons numériques comme <code>&lt;</code> (inférieur à) et <code>&gt;</code>
(plus grand que). Vous pouvez également utiliser les mots-clés <code>BETWEEN</code> et <code>AND</code>
et tout cela fonctionne avec des mots aussi bien qu'avec des nombres.
</p>
<sql-exercise data-question="Try out some comparison operators." data-comment="" data-default-text="SELECT DISTINCT city
FROM crime_scene_report
WHERE city BETWEEN 'W%' AND 'Z%';"></sql-exercise>
<p>Nous avons mentionné que les commandes SQL ne sont pas sensibles à la casse, mais les valeurs de requête <code>WHERE</code> pour
<code>=</code> et <code>LIKE</code>
le sont. Parfois, vous ne savez pas comment le texte est stocké dans la base de données. SQL fournit quelques fonctions qui peuvent vous faciliter la tâche. Ils s'appellent
<code>UPPER()</code> et
<code>LOWER()</code>, et vous pouvez probablement comprendre ce qu'ils font, surtout si vous vous baladez dans l'encadré ci-dessous.
</p>
<sql-exercise data-question="Try out UPPER() and LOWER()." data-comment="" data-default-text="SELECT DISTINCT city
FROM crime_scene_report
WHERE LOWER(city) ='sql city';"></sql-exercise>
</div>
</div>
<div id="credits" class="grid">
<div class="grid-item">
<h2>Digging deeper</h2>
<h3>Les fonctions d'agrégation SQL</h3>
<p>
Parfois, les questions que vous souhaitez poser ne sont pas aussi simples que de trouver la ligne de données correspondant à un ensemble de critères.
Vous voudrez peut-être poser des questions plus complexes telles que "Qui est la personne la plus âgée?" ou "Qui est la personne la plus petite?"
<em>Fonctions d'agrégation</em>
peut vous aider à répondre à ces questions. En fait, vous avez déjà appris une fonction d'agrégation ci-dessus, <code>COUNT</code>.
</p>
<p>
Quel âge a la personne la plus âgée avec un permis de conduire? Avec une petite quantité de données, vous pourrez peut-être simplement les observer, mais il existe des milliers d'enregistrements dans la table
<code>permis_de_conduire</code> . ( Essayez <code>COUNT</code>
si vous voulez savoir combien!) Vous ne pouvez pas simplement parcourir cette liste pour trouver la réponse.
</p>
<p>Voici quelques fonctions d'agrégation utiles fournies par SQL :
<dl>
<dt>
MAX
</dt>
<dd>
trouve la valeur maximale
</dd>
<dt>
MIN
</dt>
<dd>
trouve la valeur minimale
</dd>
<dt>
SUM
</dt>
<dd>
calcule la somme des valeurs de colonnes spécifiées
</dd>
<dt>
AVG
</dt>
<dd>
calcule la moyenne des valeurs de colonnes spécifiées
</dd>
<dt>
COUNT
</dt>
<dd>
compte le nombre de valeurs de colonnes spécifiées
</dd>
</dl>
</p>
<sql-exercise data-question="Run this query, then try some of the other aggregate functions." data-comment=""
data-default-text="SELECT max(age) FROM drivers_license;"></sql-exercise>
<p>Il existe une autre façon de trouver les valeurs minimales et maximales, tout en affichant davantage de données.
Vous pouvez contrôler l'ordre de tri des résultats que vous obtenez. C'est vraiment assez intuitif: il suffit d'utiliser
<code>ORDER BY</code>
suivi d'un nom de colonne. Cela peut être difficile quand il y a beaucoup de données!
(Lorsque les gens prennent au sérieux le travail avec SQL, ils utilisent de meilleurs outils que ce système Web!)
Par défaut, ORDER BY passe dans l'ordre "croissant " (du plus petit au plus grand, ou de A à Z), mais vous pouvez être précis avec
<code>ASC</code> pour monter, ou vous pouvez l'inverser avec <code>DESC</code>.
</p>
<sql-exercise data-question="Run this query to see how to control sort order."
data-comment="After you've run it, change ASC to DESC, or take that part out completely to see how the results differ. Try sorting on other columns."
data-default-text="SELECT * FROM drivers_license ORDER BY age ASC LIMIT 10"></sql-exercise>
<p>A présent, vous connaissez suffisamment SQL pour identifier les deux témoins. Essaiez donc !</p>
<sql-exercise data-question="Write a query that identifies the first witness."
data-comment="There's more than one way to do it, so you may learn the answer even if the results say 'Incorrect'"
data-default-text="
" data-solution="SELECT * FROM person
WHERE address_street_name = 'Northwestern Dr'
ORDER BY address_number DESC LIMIT 1;"></sql-exercise>
<sql-exercise data-question="Write a query that identifies the second witness."
data-comment="There's more than one way to do it, so you may learn the answer even if the results say 'Incorrect'"
data-default-text="
" data-solution="SELECT * FROM person
WHERE name like '%Annabel%'
AND address_street_name = 'Franklin Ave';"></sql-exercise>
</div>
</div>
<div id="joins" class="grid">
<div class="grid-item">
<h2>Faire des connexions</h2>
<h3>Joindre des tables</h3>
<p>Jusqu'à présent, nous avons posé des questions auxquelles il est possible de répondre en considérant les données d'un seul tableau.
Mais que se passe-t-il si nous devons poser des questions plus complexes qui nécessitent simultanément des données provenant de deux tables différentes?
Cest là que JOIN entre en jeu.</p>
<p>Les utilisateurs SQL plus expérimentés utilisent différents types de JOIN, vous pouvez entendre parler de jointures INTERNE, EXTERNE, GAUCHE et DROITE.
Ici, nous allons simplement parler du type le plus courant de JOIN, le JOINT INTERNE.
Comme c'est courant, vous pouvez omettre INTERNE dans vos commandes SQL.</p>
<p>
Le moyen le plus courant de joindre des tables consiste à utiliser des colonnes de clés primaires et de clés étrangères.
Reportez-vous au diagramme de relation d'entité (ERD) ci-dessus si vous ne vous souvenez pas de ce que sont ces derniers, ou pour voir les relations clés entre les tables de notre base de données.
Vous pouvez effectuer des jointures sur toutes les colonnes, mais les colonnes clés sont optimisées pour des résultats rapides.
Il est probablement plus facile de montrer comment les jointures fonctionnent avec notre système SQL interactif que de les écrire.
</p>
<sql-exercise
data-question="Run this query to identify the biggest annual earners in our database. (Again, trust us, the SSNs are all made up.)"
data-comment="Try editing the query to return more data, or to find people with different incomes. Try joining other tables together. You can use * in between SELECT and FROM here like with any other query, so try that too."
data-default-text="SELECT person.name, income.annual_income
FROM income
JOIN person
ON income.ssn = person.ssn
WHERE annual_income > 450000"></sql-exercise>
<p>Parfois, vous souhaitez connecter plus d'une table. SQL vous permet de joindre autant de tables que vous le souhaitez dans une requête.
</p>
<sql-exercise data-question="Let's see if big earners have other characteristics in common."
data-comment="This example shows how to join more than one table. It also, incidentally, shows how you can use 'aliases' for the various tables in your query so that you don't have to type as much. Finally, it shows how you can change how a column name shows up in the results, which can be handy."
data-default-text="SELECT name, annual_income as income,
gender, eye_color as eyes, hair_color as hair
FROM income i
JOIN person p
ON i.ssn = p.ssn
JOIN drivers_license dl
ON p.license_id = dl.id
WHERE annual_income > 450000"></sql-exercise>
<p>
Maintenant que vous savez comment joindre des tables, vous devriez être en mesure de trouver les transcriptions des entrevues des deux témoins que vous avez identifiés auparavant. Essaiez donc !
</p>
<sql-exercise data-question="Write a query that shows the interview transcripts for our two subjects."
data-comment="There's more than one way to do it, so you may learn the answer even if the results say 'Incorrect'. The official solution does it in one query, but you don't have to. Technically you don't even need to use a JOIN to get the transcripts, but give it a try."
data-default-text="
" data-solution="SELECT person.name, interview.transcript
FROM person JOIN interview
ON person.id = interview.person_id
WHERE person.id = 14887 OR person.id = 16371;"></sql-exercise>
</div>
</div>
<div id="go-get-em" class="grid">
<div class="grid-item">
<h3>Allez les chercher!</h3>
<p>
Vous connaissez maintenant suffisamment SQL pour résoudre le mystère. Vous devrez lire l'ERD et faire des hypothèses raisonnables, mais il n'y a pas d'autre syntaxe dont vous avez besoin!
</p>
<sql-exercise data-question="Find the murderer!"
data-comment="It will take more than one query to find the killer, but you can just keep editing this box, keeping notes on your results along the way. When you think you know the answer, go to the next section."
data-default-text="
"></sql-exercise>
</div>
</div>
<div class="grid">
<div class="grid-item">
<h3>Vérifiez votre solution</h3>
<sql-exercise data-question="Did you find the killer?" data-comment="" data-default-text="INSERT INTO solution VALUES (1, 'Insert the name of the person you found here');
SELECT value FROM solution;"></sql-exercise>
</div>
</div>
<div id="credits" class="grid">
<div class="grid-item">
<h3>Crédits</h3>
<p>SQL Murder Mystery a été créé par <a href="https://twitter.com/joonparkmusic">Joon Park</a> et <a
href="https://twitter.com/Cathy_MeiyingHe">Cathy He</a> alors qu'ils étaient membres de Knight Lab. Voir le <a
href="https://github.com/NUKnightLab/sql-mysteries">repository GitHub</a> pour plus d'informations.</p>
<p>Adapté et réalisé pour le web par <a href="https://twitter.com/joegermuska">Joe Germuska</a>.</p>
<p>Cette intrigue a été inspirée par <a href="https://github.com/veltman/clmystery">
un crime dans la 'Terminal City' voisine.</a></p>
<p>Le SQL basé sur le Web est rendu possible par <a href="https://github.com/kripken/sql.js/">SQL.js</a></p>
<p>Composants Web personnalisés de requête SQL créés et publiés dans le domaine public par Zi Chong Kao, créateur de <a
href="https://selectstarsql.com/">sélectionnez Star SQL.</a></p>
<p>Illustration du détective gracieuse de <a href="https://www.vecteezy.com/">Vectors by Vecteezy</a></p>
</div>
</div>
</div>
<footer class="footer-knightlab--dark">
<div class="container">
<div class='grid grid-center'>
<div class='column-2 column-4-phone column-4-tablet'>
<a href="http://knightlab.northwestern.edu" target="_blank">
<img src="https://cdn.knightlab.com/libs/orangeline/0.1.1/assets/logo-knightlab-stacked-dark-small.png"
style="margin-left:auto;">
</a>
<ul class="list--social text-align-center">
<li><a class="link--no-style" href="http://www.twitter.com/knightlab" target="_blank"
title="Knight Lab on Twitter"><span class="icon-twitter"></span></a></li>
<li><a class="link--no-style" href="https://www.facebook.com/knightlab" target="_blank"
title="Knight Lab on Facebook"><span class="icon-facebook"></span></a></li>
<li><a class="link--no-style" href="https://github.com/NUKnightLab/" target="_blank"
title="Knight Lab on GitHub"><span class="icon-github"></span></a></li>
</ul>
</div>
<div class='column-4 column-5-tablet column-6-phone footer-description'>
<p>
The <a title="Northwestern University" href="http://www.northwestern.edu/" target="_blank">Northwestern
University</a> Knight Lab is a team of technologists and journalists working at advancing news media
innovation through exploration and experimentation.
</p>
<div class="grid-size-2 grid-size-2-phone">
<div class="grid-item">
<a title="Medill School of Journalism, Media, Integrated Marketing Communications"
href="http://www.medill.northwestern.edu/" target="_blank">
<img src="https://cdn.knightlab.com/libs/orangeline/0.1.1/assets/logo-medill-dark.png">
</a>
</div>
<div class="grid-item">
<a title="McCormick School of Engineering" href="http://www.mccormick.northwestern.edu/" target="_blank">
<img src="https://cdn.knightlab.com/libs/orangeline/0.1.1/assets/logo-mccormick-dark.png">
</a>
</div>
</div>
</div>
</div>
<div class="grid grid-center">
<div class="grid-item">
<address itemscope="" itemtype="http://data-vocabulary.org/Organization">
<span style="display:none;" itemprop="name"
title="Knight Lab | Advancing news media innovation through exploration and experimentation."
class="address-name">Knight Lab</span>
<span itemprop="tel" class="tel">(847) 467-4971</span>
<span itemprop="address" itemscope="" itemtype="http://data-vocabulary.org/Address" class="address">
<span itemprop="street-address" class="street-address">1845 Sheridan Road</span>
<span class="room-num">Fisk #109 &amp; #111</span>
<div class="address-group">
<span itemprop="locality">Evanston,</span> <span itemprop="region">IL</span> <span
itemprop="postal-code">60208 </span>
<span style="display:none;" itemprop="geo" itemscope="" itemtype="http://www.data-vocabulary.org/Geo/"
class="geo">
Latitude: <span itemprop="latitude">42.056893</span><br>Longitude:
<span itemprop="longitude">-87.676735</span>
</span>
<a style="display:none;" href="http://knightlab.northwestern.edu" itemprop="url" class="url">Northwesten
University Knight Lab | Advancing media innovation through exploration and experimentation.</a>
</div>
</span>
</address>
<span class="copyright">© Copyright 2019 Northwestern University</span>
</div>
</div>
</div>
</footer>
<script src="https://cdn.knightlab.com/libs/orangeline/0.1.1/js/orangeline.js"></script>
<script type="text/javascript">
document.querySelector('#show-schema').addEventListener('click', function () {
document.querySelector('#experienced-schema').classList.add('show');
})
</script>
</body>
</html>

View File

@ -0,0 +1,469 @@
msgid ""
msgstr ""
msgid "Hello world"
msgstr "Bonjour le monde"
msgid "Can you find out whodunnit?"
msgstr "Trouvez le meurtrier !"
msgid "There's been a Murder in SQL City! The SQL Murder Mystery is designed to be both a self-directed lesson to"
msgstr "Il y a eu un meurtre à SQL City! Le mystère de SQL Murder Mystery est conçu pour être à la fois une leçon autodirigée pour"
msgid "learn SQL concepts and commands and a fun game for experienced SQL users to solve an intriguing crime."
msgstr "apprendre les concepts et les commandes SQL et un jeu amusant pour les utilisateurs SQL expérimentés pour résoudre un crime intrigant."
msgid "Walkthrough for SQL Beginners"
msgstr "Procédure pas à pas pour les débutants SQL"
msgid "If you're comfortable with SQL, you can"
msgstr "Si vous êtes à l'aise avec SQL, vous pouvez"
msgid "skip these explanations"
msgstr "sauter ces explications"
msgid "and put your skills to the test! Below we introduce some basic SQL concepts, and just enough detail to solve the murder. If you'd like a more complete introduction to SQL, try"
msgstr "et mettre vos compétences à l'épreuve! Ci-dessous, nous présentons quelques concepts SQL de base et juste assez de détails pour résoudre le meurtre. Si vous souhaitez une introduction plus complète à SQL, essayez de"
msgid "Select Star SQL."
msgstr "sélectionnez Star SQL."
msgid "A crime has taken place and the detective needs your help. The detective gave you the crime scene report, but you somehow lost it. You vaguely remember that the crime was a"
msgstr "Un crime a eu lieu et le détective a besoin de votre aide. Le détective vous a donné le rapport sur la scène du crime, mais vous l'avez perdu. Vous vous souvenez vaguement que le crime était un"
msgid "murder"
msgstr "meurtre"
msgid "that occurred sometime on"
msgstr "qui s'est produit le"
msgid "Jan.15, 2018"
msgstr "15 Janvier 2018"
msgid "and that it took place in"
msgstr "et qu'il a eu lieu à"
msgid "SQL City"
msgstr "SQL City"
msgid "Start by retrieving the corresponding crime scene report from the police departments database."
msgstr "Commencez par récupérer le rapport de la scène de crime correspondant dans la base de données du service de police."
msgid "All the clues to this mystery are buried in a huge database, and you need to use SQL to navigate through this vast network of information."
msgstr "Tous les indices de ce mystère sont enfouis dans une énorme base de données et vous devez utiliser SQL pour naviguer dans ce vaste réseau d'informations."
msgid "Your first step to solving the mystery is to retrieve the corresponding crime scene report from the police departments database."
msgstr "La première étape pour résoudre le mystère consiste à récupérer le rapport de scène de crime correspondant dans la base de données du service de police."
msgid "Below we'll explain from a high level the commands you need to know;"
msgstr "Ci-dessous, nou expliquons d'un point de vu haut niveau les commandes que vous devez connaître ;"
msgid "whenever you are ready, you can start adapting the examples to create your own SQL commands in search of clues --"
msgstr "dès que vous êtes prêt, vous pouvez commencer à adapter les exemples pour créer vos propres commandes SQL à la recherche d'indices,"
msgid "you can run any SQL in any of the code boxes, no matter what was in the box when you started."
msgstr "vous pouvez exécuter n'importe quelle commande SQL dans n'importe laquelle des fenêtres de code, peu importe ce qui se trouvait dans la boîte lorsque vous avez commencé."
msgid "Some Definitions"
msgstr "Quelques définitions"
msgid "What is SQL?"
msgstr "Qu'est-ce que le SQL?"
msgid "SQL, which stands for Structured Query Language, is a way to interact with relational databases and tables in a way that allows us humans to glean specific, meaningful information."
msgstr "SQL, qui signifie Structured Query Language, est un moyen d'interagir avec les bases de données relationnelles et les tables d'une manière qui permet à nous, humains, de glaner des informations spécifiques et significatives."
msgid "Wait, what is a relational database?"
msgstr "Attendez, qu'est-ce qu'une base de données relationnelle ?"
msgid "There's no single definition for the word"
msgstr "Il n'y a pas de définition unique pour le mot"
msgid "database"
msgstr "base de données"
msgid "In general, databases are systems for managing information."
msgstr "En général, les bases de données sont des systèmes de gestion de l'information."
msgid "Databases can have varying amounts of structure imposed on the data."
msgstr "Les bases de données peuvent avoir des quantités variables de structure imposées aux données."
msgid "When the data is more structured, it can help people and computers work with the data more efficiently."
msgstr "Lorsque les données sont plus structurées, cela peut aider les gens et les ordinateurs à travailler avec les données plus efficacement."
msgid "Relational databases are probably the best known kind of database. At their heart, relational databases are made up of "
msgstr "Les bases de données relationnelles sont probablement le type de base de données le plus connu. Au fond, les bases de données relationnelles sont constituées de"
msgid "tables"
msgstr "tables"
msgid ", which are a lot like spreadsheets. Each column in the table has a name and a data type (text, number, etc.), and each row in the table is a specific instance of whatever the table is 'about'."
msgstr ", qui ressemblent beaucoup à des feuilles de calcul. Chaque colonne du tableau a un nom et un type de données (texte, nombre, etc.), et chaque ligne du tableau est une instance spécifique de ce dont la table parle."
msgid "The 'relational' part comes with specific rules about how to connect data between different tables."
msgstr "La partie 'relationnelle' est accompagnée de règles spécifiques sur la manière de connecter des données entre différentes tables."
msgid "What is an ERD ?"
msgstr "Qu'est-ce qu'un ERD ?"
msgid "ERD, which stands for Entity Relationship Diagram, is a visual representation of the relationships among all relevant tables within a database."
msgstr "ERD, qui signifie Entity Relationship Diagram, est une représentation visuelle des relations entre toutes les tables pertinentes d'une base de données."
msgid "You can find the ERD for our SQL Murder Mystery database below."
msgstr "Vous pouvez trouver l'ERD pour notre base de données SQL Murder Mystery ci-dessous."
msgid "The diagram shows that each table has a name (top of the box, in bold), a list of column names (on the left) and their corresponding data types (on the right, in all caps)."
msgstr "Le diagramme montre que chaque table a un nom (en haut de la boîte, en gras), une liste de noms de colonnes (à gauche) et leurs types de données correspondants (à droite, en majuscules)."
msgid "There are also some gold key icons, blue arrow icons and gray arrows on the ERD."
msgstr "Il existe également des icônes de clés dorées, des icônes de flèche bleue et des flèches grises sur l'ERD."
msgid "A gold key indicates that the column is the primary key of the corresponding table, and a blue arrow indicates that the column is the foreign key of the corresponding table."
msgstr "Une clé dorée indique que la colonne est la clé primaire de la table correspondante et une flèche bleue indique que la colonne est la clé étrangère de la table correspondante."
msgid "Primary Key:"
msgstr "Clef primaire :"
msgid "a unique identifier for each row in a table."
msgstr "un identifiant unique pour chaque ligne d'une table."
msgid "Foreign Key:"
msgstr "Clef étrangère :"
msgid "used to reference data in one table to those in another table."
msgstr "utilisée pour référencer les données d'une table à celles d'une autre table."
msgid "If two tables are related, the matching columns, i.e. the common identifiers of the two tables, are connected by a gray arrow in the diagram."
msgstr "Si deux tables sont liées, les colonnes correspondantes, c'est-à-dire les identifiants communs des deux tables, sont reliées par une flèche grise dans le diagramme."
msgid "Here is the ERD for our database:"
msgstr "Voici l'ERD de notre base de données :"
msgid "What is a query?"
msgstr "Qu'est-ce qu'une requête ?"
msgid "If you were to look at the data in this database, you would see that the tables are huge!"
msgstr "Si vous regardiez les données de cette base de données, vous verriez que les tables sont énormes!"
msgid "There are so many data points; it simply isnt possible to go through the tables row by row to find the information we need. What are we supposed to do?"
msgstr "Il y a tellement de points de données qu'il nest tout simplement pas possible de parcourir les tableaux ligne par ligne pour trouver les informations dont nous avons besoin. Que sommes nous sensés faire?"
msgid "This is where queries come in. Queries are statements we construct to get data from the database. Queries read like natural English (for the most part)."
msgstr "C'est là qu'interviennent les requêtes. Les requêtes sont des instructions que nous construisons pour obtenir des données de la base de données. Les requêtes se lisent comme de l'anglais naturel (pour la plupart)."
msgid "Let's try a few queries against our database. For each of the boxes below, click the «run» to «execute» the query in the box."
msgstr "Essayons quelques requêtes sur notre base de données. Pour chacune des cases ci-dessous, cliquez sur «run» pour «exécuter» la requête dans la case."
msgid "You can edit the queries right here on the page to explore further. (Note that SQL commands are not case-sensitive, but it's conventional to capitalize them for readability."
msgstr "Vous pouvez modifier les requêtes ici même sur la page pour explorer davantage. (Notez que les commandes SQL ne sont pas sensibles à la casse, mais il est conventionnel de les mettre en majuscule pour plus de lisibilité."
msgid "You can also use new lines and white space as you like to format the command for readability."
msgstr "Vous pouvez également utiliser de nouvelles lignes et un espace blanc comme vous le souhaitez pour formater la commande pour plus de lisibilité."
msgid "Most database systems require you to end a query with a semicolon (';') although the system for running them in this web page is more forgiving.)"
msgstr "La plupart des systèmes de base de données exigent que vous terminiez une requête par un point-virgule (';') bien que le système pour les exécuter dans cette page Web soit plus indulgent.)"
msgid "What elements does a SQL query have ?"
msgstr "Quels éléments contient une requête SQL ?"
msgid "A SQL query can contain :"
msgstr "Une requête SQL peut contenir :"
msgid "SQL keywords (like the SELECT and FROM above)"
msgstr "Mots clés SQL (comme SELECT et FROM ci-dessus)"
msgid "Column names (like the name column above)"
msgstr "Noms de colonne (comme le nom de la colonne ci-dessus)"
msgid "Table names (like the person table above)"
msgstr "Noms de table (comme le tableau des personnes ci-dessus)"
msgid "Wildcard characters (such as "
msgstr "Caractères génériques (tels que "
msgid "Functions"
msgstr "fonctions"
msgid "Specific filtering criteria"
msgstr "Critères de filtrage spécifiques"
msgid "SQL Keywords"
msgstr "Mots clés SQL"
msgid "SQL keywords are used to specify actions in your queries."
msgstr "Les mots clés SQL sont utilisés pour spécifier des actions dans vos requêtes."
msgid "SQL keywords are not case sensitive, but we suggest using all caps for SQL keywords so that you can easily set them apart from the rest of the query."
msgstr "Les mots clés SQL ne sont pas sensibles à la casse, mais nous vous suggérons d'utiliser toutes les majuscules pour les mots clés SQL afin que vous puissiez facilement les distinguer du reste de la requête."
msgid "Some frequently used keywords are :"
msgstr "Certains mots clés fréquemment utilisés sont :"
msgid "SELECT allows us to grab data for specific columns from the database:"
msgstr "SELECT nous permet de récupérer des données pour des colonnes spécifiques de la base de données :"
msgid "* (asterisk): it is used after SELECT to grab all columns from the table;"
msgstr "* (astérisque) : il est utilisé après SELECT pour récupérer toutes les colonnes de la table ;"
msgid "column_name(s): to select specific columns, put the names of the columns after SELECT and use commas to separate them."
msgstr "nom_colonne(s) : pour sélectionner des colonnes spécifiques, mettez les noms des colonnes après SELECT et utilisez des virgules pour les séparer."
msgid "FROM allows us to specify which table(s) we care about; to select multiple tables, list the table names and use commas to separate them."
msgstr "FROM nous permet de spécifier la ou les tables qui nous intéressent; pour sélectionner plusieurs tables, listez les noms de tables et utilisez des virgules pour les séparer."
msgid "(But until you learn the JOIN keyword, you may be surprised at what happens. That will come later.)"
msgstr "(Mais tant que vous n'aurez pas appris le mot clé JOIN, vous serez peut-être surpris de ce qui se passe. Cela viendra plus tard."
msgid "The WHERE clause in a query is used to filter results by specific criteria."
msgstr "La clause WHERE dans une requête est utilisée pour filtrer les résultats selon des critères spécifiques."
msgid "Let's try some of these things."
msgstr "Essayons certaines de ces choses."
msgid "The AND keyword is used to string together multiple filtering criteria so that the filtered results meet each and every one of the criteria."
msgstr "Le mot clé AND est utilisé pour enchaîner plusieurs critères de filtrage afin que les résultats filtrés répondent à chacun des critères."
msgid "(There's also an OR keyword, which returns rows that match any of the criteria.)"
msgstr "(Il existe également un mot clé OR, qui renvoie les lignes qui correspondent à l'un des critères.)"
msgid "If you haven't found the right crime scene report yet, click \"show solution\" above, and replace the contents of the box with just the revealed command. (Leave out the initial "
msgstr "Si vous n'avez pas encore trouvé le bon rapport de scène de crime, cliquez sur \"Afficher la solution \" ci-dessus et remplacez le contenu de la boîte par la commande révélée. (Oubliez l'initiale"
msgid "If you figured out the query that shows the single crime scene report instead of a few for the same city and type, then congratulations and disregard the word \"incorrect\". You'll know if you got it!"
msgstr "Si vous avez trouvé la requête qui montre le rapport de scène de crime unique au lieu de quelques-uns pour la même ville et le même type, félicitations et ne tenez pas compte du mot «incorrect». Vous saurez si vous l'avez!"
msgid "Wildcards and other functions for partial matches"
msgstr "Caractères génériques et autres fonctions pour les correspondances partielles"
msgid "Sometimes you only know part of the information you need."
msgstr "Parfois, vous ne connaissez qu'une partie des informations dont vous avez besoin."
msgid "SQL can handle that. Special symbols that represent unknown characters are called \"wildcards,\" and SQL supports two. The most common is the"
msgstr "SQL peut gérer cela. Les symboles spéciaux qui représentent des caractères inconnus sont appelés «caractères génériques» et SQL en prend en charge deux. Le plus courant est le"
msgid "wildcard."
msgstr "joker."
msgid "When you place a"
msgstr "Lorsque vous placez un"
msgid "wildcard in a query string, the SQL system will return results that match the rest of the string exactly, and have anything (or nothing) where the wildcard is. For example,"
msgstr "caractère générique dans une chaîne de requête, le système SQL retournera des résultats qui correspondent exactement au reste de la chaîne et contiendra n'importe quoi (ou rien) là où se trouve le caractère générique. Par exemple,"
msgid "matches"
msgstr "correspondent"
msgid "and"
msgstr "et"
msgid "California"
msgstr "Californie"
msgid "The other, less commonly used wildcard, is"
msgstr "L'autre caractère générique, moins couramment utilisé, est"
msgid "This one means 'match the rest of the text, as long as there's exactly one character in exactly the position of the"
msgstr "Celui-ci signifie `correspondre au reste du texte, tant qu'il y a exactement un caractère exactement à la position du"
msgid "no matter what it is. So,"
msgstr "peu importe ce que c'est. Alors,"
msgid "would match"
msgstr "correspondrait"
msgid " but not"
msgstr " mais pas"
msgid "or"
msgstr "ou"
msgid "Important:"
msgstr "Important :"
msgid "When using wildcards, you don't use the"
msgstr "Lorsque vous utilisez des caractères génériques, vous n'utilisez pas le"
msgid "symbol; instead, you use"
msgstr "symbole; à la place, vous utilisez"
msgid "SQL also supports numeric comparisons like"
msgstr "SQL prend également en charge les comparaisons numériques comme"
msgid "(less than) and"
msgstr "(inférieur à) et"
msgid "(greater than). You can also use the keywords"
msgstr "(plus grand que). Vous pouvez également utiliser les mots-clés"
msgid "and all of those work with words as well as numbers."
msgstr "et tout cela fonctionne avec des mots aussi bien qu'avec des nombres."
msgid "We've mentioned that SQL commands are not case-sensitive, but"
msgstr "Nous avons mentionné que les commandes SQL ne sont pas sensibles à la casse, mais les valeurs de requête"
msgid "querie values for"
msgstr "pour"
msgid "are. Sometimes you don't know how the text is stored in the database. SQL provides a couple of functions which can smooth that out for you. They're called"
msgstr "le sont. Parfois, vous ne savez pas comment le texte est stocké dans la base de données. SQL fournit quelques fonctions qui peuvent vous faciliter la tâche. Ils s'appellent"
msgid "and you can probably figure out what they do, especially if you explore in the box below."
msgstr "et vous pouvez probablement comprendre ce qu'ils font, surtout si vous vous baladez dans l'encadré ci-dessous."
msgid "SQL Aggregate Functions"
msgstr "Les fonctions d'agrégation SQL"
msgid "Sometimes the questions you want to ask arent as simple as finding the row of data that fits a set of criteria."
msgstr "Parfois, les questions que vous souhaitez poser ne sont pas aussi simples que de trouver la ligne de données correspondant à un ensemble de critères."
msgid "You may want to ask more complex questions such as “Who is the oldest person?” or “Who is the shortest person?”"
msgstr "Vous voudrez peut-être poser des questions plus complexes telles que «Qui est la personne la plus âgée?» ou «Qui est la personne la plus petite?»"
msgid "Aggregate functions"
msgstr "Fonctions d'agrégation"
msgid "can help you answer these questions. In fact, you learned an aggregate function above,"
msgstr "peut vous aider à répondre à ces questions. En fait, vous avez déjà appris une fonction d'agrégation ci-dessus,"
msgid "How old is the oldest person with a drivers license? With a small amount of data, you might be able to just eyeball it, but there thousands of records in the "
msgstr "Quel âge a la personne la plus âgée avec un permis de conduire? Avec une petite quantité de données, vous pourrez peut-être simplement les observer, mais il existe des milliers d'enregistrements dans la table"
msgid "table."
msgstr "."
msgid "drivers_license"
msgstr "permis_de_conduire"
msgid "Try"
msgstr "Essayez"
msgid "if you want to know just how many!) You can't just look over that list to find the answer."
msgstr "si vous voulez savoir combien!) Vous ne pouvez pas simplement parcourir cette liste pour trouver la réponse."
msgid "Here are a few useful aggregate functions SQL provides:"
msgstr "Voici quelques fonctions d'agrégation utiles fournies par SQL :"
msgid "finds the maximum value"
msgstr "trouve la valeur maximale"
msgid "finds the minimum value"
msgstr "trouve la valeur minimale"
msgid "calculates the sum of the specified column values"
msgstr "calcule la somme des valeurs de colonnes spécifiées"
msgid "calculates the average of the specified column values"
msgstr "calcule la moyenne des valeurs de colonnes spécifiées"
msgid "counts the number of specified column values"
msgstr "compte le nombre de valeurs de colonnes spécifiées"
msgid "There's another way to find minimum and maximum values, while also seeing more of the data."
msgstr "Il existe une autre façon de trouver les valeurs minimales et maximales, tout en affichant davantage de données."
msgid "You can control the sort order of results you get. It's really quite intuitive: just use"
msgstr "Vous pouvez contrôler l'ordre de tri des résultats que vous obtenez. C'est vraiment assez intuitif: il suffit d'utiliser"
msgid "followed by a column name. It can be challenging when there's a lot of data!"
msgstr "suivi d'un nom de colonne. Cela peut être difficile quand il y a beaucoup de données!"
msgid "(When people get serious about working with SQL, they use better tools than this web-based system!)"
msgstr "(Lorsque les gens prennent au sérieux le travail avec SQL, ils utilisent de meilleurs outils que ce système Web!)"
msgid "By default, ORDER BY goes in \"ascending\" (smallest to largest, or A to Z) order, but you can be specific with"
msgstr "Par défaut, ORDER BY passe dans l'ordre \"croissant \" (du plus petit au plus grand, ou de A à Z), mais vous pouvez être précis avec"
msgid "for ascending, or you can reverse it with"
msgstr "pour monter, ou vous pouvez l'inverser avec"
msgid "By now, you know enough SQL to identify the two witnesses. Give it a try!"
msgstr "A présent, vous connaissez suffisamment SQL pour identifier les deux témoins. Essaiez donc !"
msgid "Making connections"
msgstr "Faire des connexions"
msgid "Joining tables"
msgstr "Joindre des tables"
msgid "Until now, weve been asking questions that can be answered by considering data from only a single table."
msgstr "Jusqu'à présent, nous avons posé des questions auxquelles il est possible de répondre en considérant les données d'un seul tableau."
msgid "But what if we need to ask more complex questions that simultaneously require data from two different tables?"
msgstr "Mais que se passe-t-il si nous devons poser des questions plus complexes qui nécessitent simultanément des données provenant de deux tables différentes?"
msgid "Thats where JOIN comes in."
msgstr "Cest là que JOIN entre en jeu."
msgid "More experienced SQL folks use a few different kinds of JOIN -- you may hear about INNER, OUTER, LEFT and RIGHT joins."
msgstr "Les utilisateurs SQL plus expérimentés utilisent différents types de JOIN, vous pouvez entendre parler de jointures INTERNE, EXTERNE, GAUCHE et DROITE."
msgid "Here, we'll just talk about the most common kind of JOIN, the INNER JOIN."
msgstr "Ici, nous allons simplement parler du type le plus courant de JOIN, le JOINT INTERNE."
msgid "Since it's common, you can leave out INNER in your SQL commands."
msgstr "Comme c'est courant, vous pouvez omettre INTERNE dans vos commandes SQL."
msgid "The most common way to join tables is using primary key and foreign key columns."
msgstr "Le moyen le plus courant de joindre des tables consiste à utiliser des colonnes de clés primaires et de clés étrangères."
msgid "Refer back to the Entity Relationship Diagram (ERD) above if you don't remember what those are, or to see the key relationships between tables in our database."
msgstr "Reportez-vous au diagramme de relation d'entité (ERD) ci-dessus si vous ne vous souvenez pas de ce que sont ces derniers, ou pour voir les relations clés entre les tables de notre base de données."
msgid "You can do joins on any columns, but the key columns are optimized for fast results."
msgstr "Vous pouvez effectuer des jointures sur toutes les colonnes, mais les colonnes clés sont optimisées pour des résultats rapides."
msgid "It is probably easier to show how joins work with our interactive SQL system than to write them."
msgstr "Il est probablement plus facile de montrer comment les jointures fonctionnent avec notre système SQL interactif que de les écrire."
msgid "Sometimes you want to connect more than one table. SQL lets you join as many tables in a query as you like."
msgstr "Parfois, vous souhaitez connecter plus d'une table. SQL vous permet de joindre autant de tables que vous le souhaitez dans une requête."
msgid "Now that you know how to join tables, you should be able to find the interview transcripts for the two witnesses you identified before. Give it a try!"
msgstr "Maintenant que vous savez comment joindre des tables, vous devriez être en mesure de trouver les transcriptions des entrevues des deux témoins que vous avez identifiés auparavant. Essaiez donc !"
msgid "Go Get 'em!"
msgstr "Allez les chercher!"
msgid "Now you know enough SQL to solve the mystery. You'll need to read the ERD and make some reasonable assumptions, but there's no other syntax that you need!"
msgstr "Vous connaissez maintenant suffisamment SQL pour résoudre le mystère. Vous devrez lire l'ERD et faire des hypothèses raisonnables, mais il n'y a pas d'autre syntaxe dont vous avez besoin!"
msgid "Check your solution"
msgstr "Vérifiez votre solution"
msgid "Credits"
msgstr "Crédits"
msgid "The SQL Murder Mystery was created by"
msgstr "SQL Murder Mystery a été créé par"
msgid "while they were Knight Lab fellows. See the"
msgstr "alors qu'ils étaient membres de Knight Lab. Voir le"
msgid "GitHub repository"
msgstr "repository GitHub"
msgid "for more information."
msgstr "pour plus d'informations."
msgid "Adapted and produced for the web by"
msgstr "Adapté et réalisé pour le web par"
msgid "This mystery was inspired by"
msgstr "Cette intrigue a été inspirée par"
msgid "a crime in the neighboring Terminal City."
msgstr "un crime dans la 'Terminal City' voisine."
msgid "Web-based SQL is made possible by"
msgstr "Le SQL basé sur le Web est rendu possible par"
msgid "SQL query custom web components created and released to the public domain by Zi Chong Kao, creator of"
msgstr "Composants Web personnalisés de requête SQL créés et publiés dans le domaine public par Zi Chong Kao, créateur de"
msgid "Select Star SQL."
msgstr "Star SQL."
msgid "Detective illustration courtesy of"
msgstr "Illustration du détective gracieuse de"

View File

@ -0,0 +1,26 @@
# The following Python source includes translatable strings using =_( )=
# convention, and produces the expected output when run :
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Change "fr" according to the language
import gettext
import os
import jinja2
fr = gettext.translation('fr', localedir='locale', languages=['fr'])
fr.install()
_ = fr.gettext
env = jinja2.Environment(
loader=jinja2.FileSystemLoader(
[os.path.join(os.path.dirname(__file__), 'view')]),
)
if __name__=='__main__':
template = env.get_template('walkthrough.html')
new = open("fr.html", "x")
new.write(template.render(_ = _))
new.close

View File

@ -0,0 +1,628 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" charset="utf-8">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSS -->
<link rel="stylesheet" href="https://cloud.webtype.com/css/d4767ecb-457a-4677-8761-72f890add836.css" />
<link rel="stylesheet" href="https://cdn.knightlab.com/libs/orangeline/0.1.1/css/orangeline.min.css" />
<!-- /CSS -->
<!-- FAVICONS -->
<link rel="apple-touch-icon" sizes="180x180"
href="https://cdn.knightlab.com/libs/orangeline/0.1.1/assets/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png"
href="https://cdn.knightlab.com/libs/orangeline/0.1.1/assets/favicons/favicon-32x32.png" sizes="32x32">
<link rel="icon" type="image/png"
href="https://cdn.knightlab.com/libs/orangeline/0.1.1/assets/favicons/favicon-16x16.png" sizes="16x16">
<link rel="manifest" href="https://cdn.knightlab.com/libs/orangeline/0.1.1/assets/favicons/manifest.json">
<link rel="mask-icon" href="https://cdn.knightlab.com/libs/orangeline/0.1.1/assets/favicons/safari-pinned-tab.svg"
color="#5bbad5">
<meta name="theme-color" content="#ffffff">
<!-- /FAVICONS -->
<title>The SQL Murder Mystery: Detailed Walkthrough</title>
<!-- Meta -->
<meta name="keywords" content="SQL, databases, game, fun">
<meta name="description"
content="Use SQL queries to solve the murder mystery. Suitable for beginners or experienced SQL sleuths.">
<!-- /Meta -->
<!-- Open Graph -->
<meta property="og:type" content="website" />
<meta property="og:title" content="SQL Murder Mystery" />
<meta property="og:description"
content="Use SQL queries to solve the murder mystery. Suitable for beginners or experienced SQL sleuths." />
<meta property="og:image" content="http://mystery.knightlab.com/174092-clue-illustration.png" />
<meta property="og:url" content="http://mystery.knightlab.com/walkthrough.html" />
<meta property="og:site_name" content="Knight Lab's SQL Murder Mystery" />
<meta property="fb:app_id" content="2361935160801585" />
<!-- /Open Graph -->
<!-- Twitter Card -->
<meta name="twitter:title" content="Knight Lab's SQL Murder Mystery">
<meta name="twitter:description"
content="Use SQL queries to solve the murder mystery. Suitable for beginners or experienced SQL sleuths.">
<meta name="twitter:image" content="http://mystery.knightlab.com/174092-clue-illustration.png">
<meta name="twitter:site" content="@knightlab">
<!-- /Twitter Card -->
<link rel="stylesheet" href='https://codemirror.net/lib/codemirror.css'>
<link rel="stylesheet" href="css/main.css" />
<link rel="stylesheet" href="css/neat.css" />
<script src="https://unpkg.com/@webcomponents/custom-elements@1.2.0/custom-elements.min.js"></script>
<script src="scripts/codemirror.js"></script>
<script src="scripts/codemirrorsql.js"></script>
<script src="scripts/autorefresh.js"></script>
<script src="scripts/main.js"></script>
<script>
window.onload = () => loadData('sql-murder-mystery.db');
</script>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-27829802-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag('js', new Date());
gtag('config', 'UA-27829802-1');
</script>
<title>The SQL Murder Mystery</title>
</head>
<body>
<nav id="navbar-product-top" class="navbar navbar-dark">
<ul>
<li class="logo">
<a href="http://knightlab.com">
<img src="https://cdn.knightlab.com/libs/orangeline/0.1.1/assets/knightlab-dark.png" />
</a>
</li>
</ul>
<div class="nav-mobile-menu">
<button class="button-plain">
<span class="icon-menu"></span>
</button>
</div>
<ul class="nav-right navbar-nav">
<li><a class="button button-dark button-small-tablet button-active"
href="https://knightlab.northwestern.edu/projects/">Projects</a></li>
<li><a class="button button-dark button-small-tablet " href="https://studio.knightlab.com/">Studio</a></li>
<li><a class="button button-dark button-small-tablet " href="https://localnewsinitiative.northwestern.edu/">Local
News</a></li>
<li><a class="button button-dark button-small-tablet " href="https://knightlab.northwestern.edu/posts/">Posts</a>
</li>
<li><a class="button button-dark button-small-tablet "
href="https://knightlab.northwestern.edu/community/">Community</a></li>
</ul>
</nav>
<header class="header-product">
<h1 class="product-logo product-logo-large">
SQL Murder Mystery
</h1>
<h2 class="product-tagline">{{ _("Can you find out whodunnit?") }}</h2>
</header>
<div class="container">
<div id="intro" class="grid">
<div class="grid-item">
<img src="174092-clue-illustration.png" class="img-rounded"
alt="A decorative illustration of a detective looking at an evidence board.">
<p>
{{ _("There's been a Murder in SQL City! The SQL Murder Mystery is designed to be both a self-directed lesson to") }}
{{ _("learn SQL concepts and commands and a fun game for experienced SQL users to solve an intriguing crime.") }}
</p>
</div>
</div>
<div class="grid">
<div class="grid-item">
<h2>{{ _("Walkthrough for SQL Beginners") }}</h2>
<p>
{{ _("If you're comfortable with SQL, you can") }} <a href="index.html#experienced">{{ _("skip these explanations") }}</a>
{{ _("and put your skills to the test! Below we introduce some basic SQL concepts, and just enough detail to solve the murder. If you'd like a more complete introduction to SQL, try") }}
<a href="https://selectstarsql.com/">{{ _("Select Star SQL.") }}</a>
</p>
</div>
</div>
<div class="grid">
<div class="grid-item">
<p>
{{ _("A crime has taken place and the detective needs your help. The detective gave you the crime scene report, but you somehow lost it. You vaguely remember that the crime was a") }}
<strong>{{ _("murder") }}</strong> {{ _("that occurred sometime on") }} <strong>{{ _("Jan.15, 2018") }}</strong>
{{ _("and that it took place in") }} <strong>{{ _("SQL City") }}</strong>.
{{ _("Start by retrieving the corresponding crime scene report from the police departments database.") }}
</p>
<p>
{{ _("All the clues to this mystery are buried in a huge database, and you need to use SQL to navigate through this vast network of information.") }}
{{ _("Your first step to solving the mystery is to retrieve the corresponding crime scene report from the police departments database.") }}
{{ _("Below we'll explain from a high level the commands you need to know;") }}
{{ _("whenever you are ready, you can start adapting the examples to create your own SQL commands in search of clues --") }}
{{ _("you can run any SQL in any of the code boxes, no matter what was in the box when you started.") }}
</p>
</div>
</div>
<div class="grid">
<div class="grid-item">
<h2>{{ _("Some Definitions") }}</h2>
<h3>{{ _("What is SQL?") }}</h3>
<p>
{{ _("SQL, which stands for Structured Query Language, is a way to interact with relational databases and tables in a way that allows us humans to glean specific, meaningful information.") }}
</p>
<h3>{{ _("Wait, what is a relational database?") }}</h3>
<p>{{ _("There's no single definition for the word") }}<em> {{ _("database") }}.</em>
{{ _("In general, databases are systems for managing information.") }}
{{ _("Databases can have varying amounts of structure imposed on the data.") }}
{{ _("When the data is more structured, it can help people and computers work with the data more efficiently.") }}
</p>
<p>{{ _("Relational databases are probably the best known kind of database. At their heart, relational databases are made up of ") }}
<em>{{ _("tables") }}</em>
{{ _(", which are a lot like spreadsheets. Each column in the table has a name and a data type (text, number, etc.), and each row in the table is a specific instance of whatever the table is 'about'.") }}
{{ _("The 'relational' part comes with specific rules about how to connect data between different tables.") }}
</p>
<h3>{{ _("What is an ERD ?") }}</h3>
<p>
{{ _("ERD, which stands for Entity Relationship Diagram, is a visual representation of the relationships among all relevant tables within a database.") }}
{{ _("You can find the ERD for our SQL Murder Mystery database below.") }}
{{ _("The diagram shows that each table has a name (top of the box, in bold), a list of column names (on the left) and their corresponding data types (on the right, in all caps).") }}
{{ _("There are also some gold key icons, blue arrow icons and gray arrows on the ERD.") }}
{{ _("A gold key indicates that the column is the primary key of the corresponding table, and a blue arrow indicates that the column is the foreign key of the corresponding table.") }}
<dl>
<dt>
{{ _("Primary Key:") }}
</dt>
<dd>
{{ _("a unique identifier for each row in a table.") }}
</dd>
<dt>
{{ _("Foreign Key:") }}
</dt>
<dd>
{{ _("used to reference data in one table to those in another table.") }}
</dd>
</dl>
{{ _("If two tables are related, the matching columns, i.e. the common identifiers of the two tables, are connected by a gray arrow in the diagram.") }}
</p>
<p>{{ _("Here is the ERD for our database:") }}
</p>
<img src="schema.png" width='1002' height='491'>
</div>
</div>
<div class="grid">
<div class="grid-item">
<h2>
{{ _("What is a query?") }}
</h2>
<p>
{{ _("If you were to look at the data in this database, you would see that the tables are huge!") }}
{{ _("There are so many data points; it simply isnt possible to go through the tables row by row to find the information we need. What are we supposed to do?") }}
</p>
<p>
{{ _("This is where queries come in. Queries are statements we construct to get data from the database. Queries read like natural English (for the most part).") }}
{{ _("Let's try a few queries against our database. For each of the boxes below, click the \"run\" to \"execute\" the query in the box.") }}
{{ _("You can edit the queries right here on the page to explore further. (Note that SQL commands are not case-sensitive, but it's conventional to capitalize them for readability.") }}
{{ _("You can also use new lines and white space as you like to format the command for readability.") }}
{{ _("Most database systems require you to end a query with a semicolon (';') although the system for running them in this web page is more forgiving.)") }}
</p>
<sql-exercise data-question="Just how many people are in this database?"
data-comment="Don't worry about exactly what this means, but know that you can change 'person' to any other table from the ERD to learn how many rows that table has. Try it!"
data-default-text="SELECT count(*)
FROM person;"></sql-exercise>
<sql-exercise data-question="What do we know about those people?"
data-comment="If you want all the data for each row in a table, use '*' after 'SELECT'. As you just learned, there are thousands of people, so rather than see all of them, we'll limit the results to just the first 10. Run this, then change the table name or limit number and see what happens."
data-default-text="SELECT * FROM person LIMIT 10;"></sql-exercise>
<sql-exercise data-question="What are possible values for a column?"
data-comment='When working with data, always see if you can find documentation that explains the database structure (like the ERD) and valid values. But sometimes thats not available. Here we show how the DISTINCT keyword can give you a quick look at which values are in the database. After you run it, delete the word DISTINCT and run it again. See the difference? (After you try that, you may want to click the "reset" button and run one more time before you continue.)'
data-default-text="SELECT DISTINCT type FROM crime_scene_report;"></sql-exercise>
</div>
</div>
<div class="grid">
<div class="grid-item">
<h3>{{ _("What elements does a SQL query have ?") }}</h3>
<p>{{ _("A SQL query can contain :") }}
<ul>
<li>{{ _("SQL keywords (like the SELECT and FROM above)") }}</li>
<li>{{ _("Column names (like the name column above)") }}</li>
<li>{{ _("Table names (like the person table above)") }}</li>
<li>{{ _("Wildcard characters (such as ") }} <code>%</code>)</li>
<li>{{ _("Functions") }}</li>
<li>{{ _("Specific filtering criteria") }}</li>
<li>{{ _("Etc") }}</li>
</ul>
</p>
<h4 id="sql-keywords">{{ _("SQL Keywords") }}</h4>
<p>
{{ _("SQL keywords are used to specify actions in your queries.") }}
{{ _("SQL keywords are not case sensitive, but we suggest using all caps for SQL keywords so that you can easily set them apart from the rest of the query.") }}
{{ _("Some frequently used keywords are :") }}
</p>
<h5>{{ _("SELECT") }}</h5>
<p>{{ _("SELECT allows us to grab data for specific columns from the database:") }}</p>
<ul>
<li>
{{ _("* (asterisk): it is used after SELECT to grab all columns from the table;") }}
</li>
<li>
{{ _("column_name(s): to select specific columns, put the names of the columns after SELECT and use commas to separate them.") }}
</li>
</ul>
<h5>FROM</h5>
<p>{{ _("FROM allows us to specify which table(s) we care about; to select multiple tables, list the table names and use commas to separate them.") }}
{{ _("(But until you learn the JOIN keyword, you may be surprised at what happens. That will come later.)") }}</p>
<h5>WHERE</h5>
<p>{{ _("The WHERE clause in a query is used to filter results by specific criteria.") }}</p>
<p>{{ _("Let's try some of these things.") }}</p>
<sql-exercise
data-question="Here's a simple query to get everything about a specific person. (Don't worry&mdash;all of the SSNs are made up.) "
data-comment="Note that you need to use single straight quotes (') around literal text so the database can tell it apart from table and column names. After you run it, try again with Yessenia Fossen, Ted Denfip or Davina Gangwer."
data-default-text="SELECT * FROM person WHERE name = 'Kinsey Erickson'"></sql-exercise>
<p>{{ _("The AND keyword is used to string together multiple filtering criteria so that the filtered results meet each and every one of the criteria.") }}
{{ _("(There's also an OR keyword, which returns rows that match any of the criteria.)") }}</p>
<sql-exercise data-question="This query only returns reports about a specific type of crime in a specific city."
data-comment=" Notice that when querying for text values, you must match the data as it is in the database. Try changing 'Chicago' to 'chicago' and running the statement. Then, see if you can edit this SQL statement to find the first clue based on the prompt above."
data-default-text="SELECT * FROM crime_scene_report
WHERE type = 'theft'
AND city = 'Chicago';" data-solution="SELECT * FROM crime_scene_report
WHERE type = 'murder'
AND city = 'SQL City';"></sql-exercise>
<p>{{ _("If you haven't found the right crime scene report yet, click \"show solution\" above, and replace the contents of the box with just the revealed command. (Leave out the initial ") }}
<code>/*</code>)
{{ _("If you figured out the query that shows the single crime scene report instead of a few for the same city and type, then congratulations and disregard the word \"incorrect\". You'll know if you got it!") }}
</p>
<h4 id='wildcards'>{{ _("Wildcards and other functions for partial matches") }}</h4>
<p>{{ _("Sometimes you only know part of the information you need.") }}
{{ _("SQL can handle that. Special symbols that represent unknown characters are called \"wildcards,\" and SQL supports two. The most common is the") }}
<code>%</code>
{{ _("wildcard.") }}</p>
<p>{{ _("When you place a") }} <code>%</code>
{{ _("wildcard in a query string, the SQL system will return results that match the rest of the string exactly, and have anything (or nothing) where the wildcard is. For example,") }}
<code>'Ca%a'</code> {{ _("matches") }} <code>Canada</code> {{ _("and") }} <code>{{ _("California") }}</code>.</p>
<p>{{ _("The other, less commonly used wildcard, is") }} <code>_</code>.
{{ _("This one means 'match the rest of the text, as long as there's exactly one character in exactly the position of the") }}
<code>_</code>, {{ _("no matter what it is. So,") }}
<code>'B_b'</code> {{ _("would match") }}<code>'Bob'</code> {{ _("and") }} <code>'Bub'</code>{{ _(" but not") }} <code>'Babe'</code>{{ _("or") }}
<code>'Bb'</code>.</p>
<p><strong>{{ _("Important:") }}</strong> {{ _("When using wildcards, you don't use the") }} <code>=</code> {{ _("symbol; instead, you use") }}
<code>LIKE</code>.
</p>
<sql-exercise data-question="Try out some wildcards."
data-comment="Once you run this command, try variations like 'Irvin_' and 'I%e' -- and then explore some more."
data-default-text="SELECT DISTINCT city
FROM crime_scene_report
WHERE city LIKE 'I%';"></sql-exercise>
<p>{{ _("SQL also supports numeric comparisons like") }} <code>&lt;</code> {{ _("(less than) and") }} <code>&gt;</code>
{{ _("(greater than). You can also use the keywords") }} <code>BETWEEN</code> {{ _("and") }} <code>AND</code>
{{ _("and all of those work with words as well as numbers.") }}
</p>
<sql-exercise data-question="Try out some comparison operators." data-comment="" data-default-text="SELECT DISTINCT city
FROM crime_scene_report
WHERE city BETWEEN 'W%' AND 'Z%';"></sql-exercise>
<p>{{ _("We've mentioned that SQL commands are not case-sensitive, but") }} <code>WHERE</code> {{ _("querie values for") }}
<code>=</code> {{ _("and") }} <code>LIKE</code>
{{ _("are. Sometimes you don't know how the text is stored in the database. SQL provides a couple of functions which can smooth that out for you. They're called") }}
<code>UPPER()</code> {{ _("and") }}
<code>LOWER()</code>, {{ _("and you can probably figure out what they do, especially if you explore in the box below.") }}
</p>
<sql-exercise data-question="Try out UPPER() and LOWER()." data-comment="" data-default-text="SELECT DISTINCT city
FROM crime_scene_report
WHERE LOWER(city) ='sql city';"></sql-exercise>
</div>
</div>
<div id="credits" class="grid">
<div class="grid-item">
<h2>{{ _("Digging deeper") }}</h2>
<h3>{{ _("SQL Aggregate Functions") }}</h3>
<p>
{{ _("Sometimes the questions you want to ask arent as simple as finding the row of data that fits a set of criteria.") }}
{{ _("You may want to ask more complex questions such as “Who is the oldest person?” or “Who is the shortest person?”") }}
<em>{{ _("Aggregate functions") }}</em>
{{ _("can help you answer these questions. In fact, you learned an aggregate function above,") }} <code>COUNT</code>.
</p>
<p>
{{ _("How old is the oldest person with a drivers license? With a small amount of data, you might be able to just eyeball it, but there thousands of records in the ") }}
<code>{{ _("drivers_license") }}</code> {{ _("table.") }} ( {{ _("Try") }} <code>COUNT</code>
{{ _("if you want to know just how many!) You can't just look over that list to find the answer.") }}
</p>
<p>{{ _("Here are a few useful aggregate functions SQL provides:") }}
<dl>
<dt>
MAX
</dt>
<dd>
{{ _("finds the maximum value") }}
</dd>
<dt>
MIN
</dt>
<dd>
{{ _("finds the minimum value") }}
</dd>
<dt>
SUM
</dt>
<dd>
{{ _("calculates the sum of the specified column values") }}
</dd>
<dt>
AVG
</dt>
<dd>
{{ _("calculates the average of the specified column values") }}
</dd>
<dt>
COUNT
</dt>
<dd>
{{ _("counts the number of specified column values") }}
</dd>
</dl>
</p>
<sql-exercise data-question="Run this query, then try some of the other aggregate functions." data-comment=""
data-default-text="SELECT max(age) FROM drivers_license;"></sql-exercise>
<p>{{ _("There's another way to find minimum and maximum values, while also seeing more of the data.") }}
{{ _("You can control the sort order of results you get. It's really quite intuitive: just use") }}
<code>ORDER BY</code>
{{ _("followed by a column name. It can be challenging when there's a lot of data!") }}
{{ _("(When people get serious about working with SQL, they use better tools than this web-based system!)") }}
{{ _("By default, ORDER BY goes in \"ascending\" (smallest to largest, or A to Z) order, but you can be specific with") }}
<code>ASC</code> {{ _("for ascending, or you can reverse it with") }} <code>DESC</code>.
</p>
<sql-exercise data-question="Run this query to see how to control sort order."
data-comment="After you've run it, change ASC to DESC, or take that part out completely to see how the results differ. Try sorting on other columns."
data-default-text="SELECT * FROM drivers_license ORDER BY age ASC LIMIT 10"></sql-exercise>
<p>{{ _("By now, you know enough SQL to identify the two witnesses. Give it a try!") }}</p>
<sql-exercise data-question="Write a query that identifies the first witness."
data-comment="There's more than one way to do it, so you may learn the answer even if the results say 'Incorrect'"
data-default-text="
" data-solution="SELECT * FROM person
WHERE address_street_name = 'Northwestern Dr'
ORDER BY address_number DESC LIMIT 1;"></sql-exercise>
<sql-exercise data-question="Write a query that identifies the second witness."
data-comment="There's more than one way to do it, so you may learn the answer even if the results say 'Incorrect'"
data-default-text="
" data-solution="SELECT * FROM person
WHERE name like '%Annabel%'
AND address_street_name = 'Franklin Ave';"></sql-exercise>
</div>
</div>
<div id="joins" class="grid">
<div class="grid-item">
<h2>{{ _("Making connections") }}</h2>
<h3>{{ _("Joining tables") }}</h3>
<p>{{ _("Until now, weve been asking questions that can be answered by considering data from only a single table.") }}
{{ _("But what if we need to ask more complex questions that simultaneously require data from two different tables?") }}
{{ _("Thats where JOIN comes in.") }}</p>
<p>{{ _("More experienced SQL folks use a few different kinds of JOIN -- you may hear about INNER, OUTER, LEFT and RIGHT joins.") }}
{{ _("Here, we'll just talk about the most common kind of JOIN, the INNER JOIN.") }}
{{ _("Since it's common, you can leave out INNER in your SQL commands.") }}</p>
<p>
{{ _("The most common way to join tables is using primary key and foreign key columns.") }}
{{ _("Refer back to the Entity Relationship Diagram (ERD) above if you don't remember what those are, or to see the key relationships between tables in our database.") }}
{{ _("You can do joins on any columns, but the key columns are optimized for fast results.") }}
{{ _("It is probably easier to show how joins work with our interactive SQL system than to write them.") }}
</p>
<sql-exercise
data-question="Run this query to identify the biggest annual earners in our database. (Again, trust us, the SSNs are all made up.)"
data-comment="Try editing the query to return more data, or to find people with different incomes. Try joining other tables together. You can use * in between SELECT and FROM here like with any other query, so try that too."
data-default-text="SELECT person.name, income.annual_income
FROM income
JOIN person
ON income.ssn = person.ssn
WHERE annual_income > 450000"></sql-exercise>
<p>{{ _("Sometimes you want to connect more than one table. SQL lets you join as many tables in a query as you like.") }}
</p>
<sql-exercise data-question="Let's see if big earners have other characteristics in common."
data-comment="This example shows how to join more than one table. It also, incidentally, shows how you can use 'aliases' for the various tables in your query so that you don't have to type as much. Finally, it shows how you can change how a column name shows up in the results, which can be handy."
data-default-text="SELECT name, annual_income as income,
gender, eye_color as eyes, hair_color as hair
FROM income i
JOIN person p
ON i.ssn = p.ssn
JOIN drivers_license dl
ON p.license_id = dl.id
WHERE annual_income > 450000"></sql-exercise>
<p>
{{ _("Now that you know how to join tables, you should be able to find the interview transcripts for the two witnesses you identified before. Give it a try!") }}
</p>
<sql-exercise data-question="Write a query that shows the interview transcripts for our two subjects."
data-comment="There's more than one way to do it, so you may learn the answer even if the results say 'Incorrect'. The official solution does it in one query, but you don't have to. Technically you don't even need to use a JOIN to get the transcripts, but give it a try."
data-default-text="
" data-solution="SELECT person.name, interview.transcript
FROM person JOIN interview
ON person.id = interview.person_id
WHERE person.id = 14887 OR person.id = 16371;"></sql-exercise>
</div>
</div>
<div id="go-get-em" class="grid">
<div class="grid-item">
<h3>{{ _("Go Get 'em!") }}</h3>
<p>
{{ _("Now you know enough SQL to solve the mystery. You'll need to read the ERD and make some reasonable assumptions, but there's no other syntax that you need!") }}
</p>
<sql-exercise data-question="Find the murderer!"
data-comment="It will take more than one query to find the killer, but you can just keep editing this box, keeping notes on your results along the way. When you think you know the answer, go to the next section."
data-default-text="
"></sql-exercise>
</div>
</div>
<div class="grid">
<div class="grid-item">
<h3>{{ _("Check your solution") }}</h3>
<sql-exercise data-question="Did you find the killer?" data-comment="" data-default-text="INSERT INTO solution VALUES (1, 'Insert the name of the person you found here');
SELECT value FROM solution;"></sql-exercise>
</div>
</div>
<div id="credits" class="grid">
<div class="grid-item">
<h3>{{ _("Credits") }}</h3>
<p>{{ _("The SQL Murder Mystery was created by") }} <a href="https://twitter.com/joonparkmusic">Joon Park</a> {{ _("and") }} <a
href="https://twitter.com/Cathy_MeiyingHe">Cathy He</a> {{ _("while they were Knight Lab fellows. See the") }} <a
href="https://github.com/NUKnightLab/sql-mysteries">{{ _("GitHub repository") }}</a> {{ _("for more information.") }}</p>
<p>{{ _("Adapted and produced for the web by") }} <a href="https://twitter.com/joegermuska">Joe Germuska</a>.</p>
<p>{{ _("This mystery was inspired by") }} <a href="https://github.com/veltman/clmystery">
{{ _("a crime in the neighboring Terminal City.") }}</a></p>
<p>{{ _("Web-based SQL is made possible by") }} <a href="https://github.com/kripken/sql.js/">SQL.js</a></p>
<p>{{ _("SQL query custom web components created and released to the public domain by Zi Chong Kao, creator of") }} <a
href="https://selectstarsql.com/">{{ _("Select Star SQL.") }}</a></p>
<p>{{ _("Detective illustration courtesy of") }} <a href="https://www.vecteezy.com/">{{ _("Vectors by Vecteezy") }}</a></p>
</div>
</div>
</div>
<footer class="footer-knightlab--dark">
<div class="container">
<div class='grid grid-center'>
<div class='column-2 column-4-phone column-4-tablet'>
<a href="http://knightlab.northwestern.edu" target="_blank">
<img src="https://cdn.knightlab.com/libs/orangeline/0.1.1/assets/logo-knightlab-stacked-dark-small.png"
style="margin-left:auto;">
</a>
<ul class="list--social text-align-center">
<li><a class="link--no-style" href="http://www.twitter.com/knightlab" target="_blank"
title="Knight Lab on Twitter"><span class="icon-twitter"></span></a></li>
<li><a class="link--no-style" href="https://www.facebook.com/knightlab" target="_blank"
title="Knight Lab on Facebook"><span class="icon-facebook"></span></a></li>
<li><a class="link--no-style" href="https://github.com/NUKnightLab/" target="_blank"
title="Knight Lab on GitHub"><span class="icon-github"></span></a></li>
</ul>
</div>
<div class='column-4 column-5-tablet column-6-phone footer-description'>
<p>
The <a title="Northwestern University" href="http://www.northwestern.edu/" target="_blank">Northwestern
University</a> Knight Lab is a team of technologists and journalists working at advancing news media
innovation through exploration and experimentation.
</p>
<div class="grid-size-2 grid-size-2-phone">
<div class="grid-item">
<a title="Medill School of Journalism, Media, Integrated Marketing Communications"
href="http://www.medill.northwestern.edu/" target="_blank">
<img src="https://cdn.knightlab.com/libs/orangeline/0.1.1/assets/logo-medill-dark.png">
</a>
</div>
<div class="grid-item">
<a title="McCormick School of Engineering" href="http://www.mccormick.northwestern.edu/" target="_blank">
<img src="https://cdn.knightlab.com/libs/orangeline/0.1.1/assets/logo-mccormick-dark.png">
</a>
</div>
</div>
</div>
</div>
<div class="grid grid-center">
<div class="grid-item">
<address itemscope="" itemtype="http://data-vocabulary.org/Organization">
<span style="display:none;" itemprop="name"
title="Knight Lab | Advancing news media innovation through exploration and experimentation."
class="address-name">Knight Lab</span>
<span itemprop="tel" class="tel">(847) 467-4971</span>
<span itemprop="address" itemscope="" itemtype="http://data-vocabulary.org/Address" class="address">
<span itemprop="street-address" class="street-address">1845 Sheridan Road</span>
<span class="room-num">Fisk #109 &amp; #111</span>
<div class="address-group">
<span itemprop="locality">Evanston,</span> <span itemprop="region">IL</span> <span
itemprop="postal-code">60208 </span>
<span style="display:none;" itemprop="geo" itemscope="" itemtype="http://www.data-vocabulary.org/Geo/"
class="geo">
Latitude: <span itemprop="latitude">42.056893</span><br>Longitude:
<span itemprop="longitude">-87.676735</span>
</span>
<a style="display:none;" href="http://knightlab.northwestern.edu" itemprop="url" class="url">Northwesten
University Knight Lab | Advancing media innovation through exploration and experimentation.</a>
</div>
</span>
</address>
<span class="copyright">© Copyright 2019 Northwestern University</span>
</div>
</div>
</div>
</footer>
<script src="https://cdn.knightlab.com/libs/orangeline/0.1.1/js/orangeline.js"></script>
<script type="text/javascript">
document.querySelector('#show-schema').addEventListener('click', function () {
document.querySelector('#experienced-schema').classList.add('show');
})
</script>
</body>
</html>

View File

@ -57,18 +57,16 @@
<script>
window.onload = () => loadData('sql-murder-mystery.db');
</script>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-27829802-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-8F4WPDMPL5"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-27829802-1');
</script>
gtag('config', 'G-8F4WPDMPL5');
</script>
<title>The SQL Murder Mystery</title>
</head>
@ -295,7 +293,7 @@ WHERE city LIKE 'I%';"></sql-exercise>
FROM crime_scene_report
WHERE city BETWEEN 'W%' AND 'Z%';"></sql-exercise>
<p>We've mentioned that SQL commands are not case-sensitive, but <code>WHERE</code> querie values for
<p>We've mentioned that SQL commands are not case-sensitive, but <code>WHERE</code> query values for
<code>=</code> and <code>LIKE</code> are. Sometimes you don't know how the text is stored in the database. SQL provides a couple of functions which can smooth that out for you. They're called <code>UPPER()</code> and
<code>LOWER()</code>, and you can probably figure out what they do, especially if you explore in the box below.
</p>
@ -358,7 +356,7 @@ WHERE LOWER(city) ='sql city';"></sql-exercise>
<sql-exercise data-question="Run this query, then try some of the other aggregate functions." data-comment="" data-default-text="SELECT max(age) FROM drivers_license;"></sql-exercise>
<p>There's another way to find minimum and maximum values, while also seeing more of the data. You can control the sort order of results you get. It's really quite intuitive: just use <code>ORDER BY</code> followed by a column name. It can
be challenging when there's a lot of data! (When people get serious about working with SQL, they use better tools than this web-based system!) By default, ORDER BY goes in "ascending" (smallest to largest, or A to Z) order, but you
be challenging when there's a lot of data! (When people get serious about working with SQL, they use better tools than this web-based system.) By default, ORDER BY goes in "ascending" (smallest to largest, or A to Z) order, but you
can be specific with <code>ASC</code> for ascending, or you can reverse it with <code>DESC</code>.
</p>
<sql-exercise data-question="Run this query to see how to control sort order." data-comment="After you've run it, change ASC to DESC, or take that part out completely to see how the results differ. Try sorting on other columns." data-default-text="SELECT * FROM drivers_license ORDER BY age ASC LIMIT 10"></sql-exercise>