Follow along with the video below to see how to install our site as a web app on your home screen.
Huomio: This feature may not be available in some browsers.
rData = bytearray(6)
uart.readinto(rData)
Struct:lla tuo onnistuu:Olen koittanut taas laoitella koodaukseen tutustumista ja hieman askarrella microPythonilla. Koitan värkkäillä venttiillien säätöä. Venttiilit saisivat parametrit sarjaliikenteellä ja stm32 hoitaa sitten ohjaukset.
Olen koittanut ensin saada koodin palasia toimimaan "yksinään" ja lopuksi sitten koitan saada ympättyä kaikki yhteen. Nyt askartelen tuota sarjaliikennettä, se "toimii", mutta en ole keksinyt miten saan yhdistettyä tavuja?
Eli luen tavut ja lykkään array:hin
Koodi:rData = bytearray(6) uart.readinto(rData)
Tuosta on/olisi tarkoitus poimia parameterit talteen, koittaa väsätä joku crc yms. noiden yksittäisten tavujen "käyttö" onnistuu, mutta niiden yhdistäminen? Eli haluasin, että osa tavuista yhdistettäisiin jotta saisin 16bit inttejä.
Eli esim nuo 6 tavua 8bit, 16bit, 16bit, 8bit. Jolloin [1:2] ja [3:4] "nivotaan yhteen".
Kiitoksia tästä, toimii! Sulla taisi tulla typo tuohon, eli eksyi = merkki joukkoon?Struct:lla tuo onnistuu:
struct.unpack('=bhhb',rData)
![]()
struct — Interpret bytes as packed binary data
Source code: Lib/struct.py This module converts between Python values and C structs represented as Python bytes objects. Compact format strings describe the intended conversions to/from Python valu...docs.python.org
Kiitoksia minunkin puolesta, noin kolme vuotta sitten tuli tehtyä yksi konversiosofta jossa käpisteltiin aika paljon bytearrayita ja silloin koitin jotain vastaavaa googletella mutta ei sattunut osumaan vastaan tuota. Tuli sitten vähän vastaava toiminnallisuus jälleen kerran koodattua ihan itse alusta asti ja tuo konversiosofta on ehkä juuri sen takia aikamoista spagettikoodia paikoitellen. Siinä on pari bugiakin vielä mutta jos nyt ehkä jaksaisi siivoilla koodia ja koittaa jos saisi ne pari bugiakin pois. Pikkuhiljaa alkaa kyllä tuntua että pythonista löytyy ihan mitä funktioita sun muita vaan kunhan vaan keksii ne.Struct:lla tuo onnistuu:
struct.unpack('=bhhb',rData)
![]()
struct — Interpret bytes as packed binary data
Source code: Lib/struct.py This module converts between Python values and C structs represented as Python bytes objects. Compact format strings describe the intended conversions to/from Python valu...docs.python.org
Hmm, yhtäsuuruusmerkki heittää "Bad typecoden". Google auttaa, eli ustruct ei tue tuota, "Supported size/byte order prefixes: @, <, >, ! "Yhtäsuuruus merkki kertoo onko data big tai little endian. Pikaisesti kun testasin mulla niin ei toiminut ilman sitä. Riippuunee python versiosta tarviiko sitä vai ei. Tuon pitäisi kuitenkin toimia kaikilla versioilla.
01 01 01 01 01 01
bytearray(b'\x01\x01\x01\x01\x01\x01\x00')
(1, 257, 257, 0)
Oisko auttaa tuossa arrayn koossa? Eli miksi tuo "ei mahdu" bytearray(6) vaan vaatii 7.
struct.calcsize('BHHB') palauttaa 7.
Kiitoksia, tämä olikin simpppeli ja olisi itsekkin pitänyt varmaan tuosta dokkarista tajuta, eli toimii hienosti kun lisää bytorderin jolla size on "standard".Kuten tuossa struct dokkarin alussa olevassa nootissa sanotaan, ilman tuota ensimmäistä tavukoko/järjestys/tasausmäärettä mennään oletuksena raudan C natiivilla joka ei välttämättä ole pakattua dataa: Data structure alignment - Wikipedia
TL;DR
Jos micropythonille ei kelpaa = niin joudut käyttämään <:ä tai >:ä riippuen käytetystä endiannessista tai laittamaan paddingit oikeaan paikkaan.
rParams = struct.unpack('<BHHB', rData)
x = []
x.extend(rParams)
if x[1] == 1:
duty = x[2]
else:
duty = 100
Tuo struct siis palauttaa tuplen, ennen kuin kauheasti kikkailen lisää niin käytän extendiä muuttaakseni taas tuon tuplen:
Eli onko tuo extendin käyttö ihan ok?Koodi:rParams = struct.unpack('<BHHB', rData) x = [] x.extend(rParams) if x[1] == 1: duty = x[2] else: duty = 100
x = list(rParams)
# Tai jos ei tuplea tarvita mihinkään niin suoraan listaksi
rParams = list(struct.unpack('<BHHB', rData))
Aa en tajununnutkaan, että ton voi heittää suoraan listaksi. Paljon kiitoksiaEi tuossa välttämättä extendiä tarvita, toimii toki mutta itse tekisin jotakin tällaista
Koodi:x = list(rParams) # Tai jos ei tuplea tarvita mihinkään niin suoraan listaksi rParams = list(struct.unpack('<BHHB', rData))
Tuplekin toimisi sellaisenaan tuossa lyhyessä pätkässä minkä laitoit, mutta oletan että käytät sitä muuhunkin niin paha sanoa.
Käytän yhdessä projektissa ORMia (Prisma) ja projekti pitää sisällään tietokannan skeematiedoston (schema.prisma). Tarvitsisin tuota samaa skeematiedostoa sivuprojektissa.
Miten toteutan tuon tiedoston jakamisen kahden eri projektin kesken? En voi vaan kopipastettaa tuota tiedostoa, koska se voi muuttua ja muuttuukin usein devausvaiheessa.
Toivottavasti ymmärsin oikein, eli kyseessä NodeJS-ympäristö? Ja schema.prisma lienee module.exports kamaa?Käytän yhdessä projektissa ORMia (Prisma) ja projekti pitää sisällään tietokannan skeematiedoston (schema.prisma). Tarvitsisin tuota samaa skeematiedostoa sivuprojektissa.
Miten toteutan tuon tiedoston jakamisen kahden eri projektin kesken? En voi vaan kopipastettaa tuota tiedostoa, koska se voi muuttua ja muuttuukin usein devausvaiheessa.
{
dependencies: {
"prisma-schema-local": "file:/<path_to_file>/schema.prisma",
"prisma-schema-git": "git:<url_to_repo/schema.prisma",
}
}
Juu Nodesta kyse. Miten tämä käytännössä menee? Tuo prisma olettaa että projektinToivottavasti ymmärsin oikein, eli kyseessä NodeJS-ympäristö? Ja schema.prisma lienee module.exports kamaa?
Helpointa lienee viitata package.json:issa kyseiseen tiedostoon joko paikallisesti tai sitten git-repon kautta, tyyliin:
Ja tämän jälkeen vain esimerkiksi `import PrismaSchema from 'prisma-schema-local'`JavaScript:{ dependencies: { "prisma-schema-local": "file:/<path_to_file>/schema.prisma", "prisma-schema-git": "git:<url_to_repo/schema.prisma", } }
./prisma kansiosta löytyy tuo prisma.schema-tiedosto.TauluA
id Int
name String
--------------
TauluB
id Int
name String
tauluAid
Tuli eteen toinen kysymys.
Mikä on oikea tapa määrittää muuttuvia relaatioita SQL:ssä?
Esimerkki:
Koodi:TauluA id Int name String -------------- TauluB id Int name String tauluAid
Eli mulla on kaksi taulua A ja B. Kun haen TauluB:stä jonkun rivin, niin sen pitäisi vuodesta riippuen viitata tiettyyn TauluA:n riviin. Nyt olen tehny tuon siten, että päivitän TauluB:hen aina tällä hetkellä voimassa olevan viittauksen, mutta tällä tavalla esim. kaikki viime vuoden tilastot ovat rikki, koska referenssi on vaihtunut.
Tuli eteen toinen kysymys.
Mikä on oikea tapa määrittää muuttuvia relaatioita SQL:ssä?
Esimerkki:
Koodi:TauluA id Int name String -------------- TauluB id Int name String tauluAid
Eli mulla on kaksi taulua A ja B. Kun haen TauluB:stä jonkun rivin, niin sen pitäisi vuodesta riippuen viitata tiettyyn TauluA:n riviin. Nyt olen tehny tuon siten, että päivitän TauluB:hen aina tällä hetkellä voimassa olevan viittauksen, mutta tällä tavalla esim. kaikki viime vuoden tilastot ovat rikki, koska referenssi on vaihtunut.
TauluA (
id Int,
name String
)
TauluB (
id Int,
name String
)
LinkkitauluAB (
tauluAId int,
tauluBId int,
vuosi int
)
Jees, tämä tuntuu helpolta ratkaisulta. Tulee tallennettua tietokantaa turhaa tietoa, koska noita muuttuvia kenttiä ei ole montaa, mutta ei ole toisaalta noita rivejäkään.En täysin ymmärrä kysymystä, mutta eikö riitä että lisäät toiseen tai tarvittaessa molempiin tauluihin kentän vuosi, jos data ei voi jostain syystä olla yhdessä taulussa, mikä olisi varmaan sen yksinkertaisin vaihtoehto.
Jos taas teet joinin taulujen välillä samalla id:llä, niin samassa taulussa voi olla sama "id" eri vuosillakin eli eri riveinä. Tosin id-kenttä ei voi olla silloin uniikki toisessa taulussa, mutta onhan tuossa jo esim. tuo "taulun id" kenttä, mitä voi käyttää joiniin. Id:t on tapana pitää uniikkeina tauluissa.
// luodaan palvelin porttiin 8080
ServerSocket server = new ServerSocket(8080);
while (true) {
// odotetaan pyyntöä
Socket socket = server.accept();
// luetaan pyyntö
Scanner lukija = new Scanner(socket.getInputStream());
// ...
// kirjoitetaan vastaus
PrintWriter kirjoittaja = new PrintWriter(socket.getOutputStream());
// ...
Sillä varmaan viitataan siihen HTTP-pyyntöön. Eli jos pyyntö onYritän opiskella Moocista tuota web-palvelinohjelmointia (Web-palvelimen toiminta - Web-palvelinohjelmointi Java 2020), mutta näköjään hukassa heti alkuun.
Kyseessä tuo Hello server-tehtävä.
Jos luon palvelimen näin esimerkin mukaan:
Koodi:// luodaan palvelin porttiin 8080 ServerSocket server = new ServerSocket(8080); while (true) { // odotetaan pyyntöä Socket socket = server.accept(); // luetaan pyyntö Scanner lukija = new Scanner(socket.getInputStream()); // ... // kirjoitetaan vastaus PrintWriter kirjoittaja = new PrintWriter(socket.getOutputStream()); // ...
Ja tehtävän annossa on maininta: "Jos pyydetty polku on /quit, tulee palvelin sammuttaa."
Niin mistä löydän tuon polun?
GET /quit HTTP/1.1
Yritän opiskella Moocista tuota web-palvelinohjelmointia (Web-palvelimen toiminta - Web-palvelinohjelmointi Java 2020), mutta näköjään hukassa heti alkuun.
Kyseessä tuo Hello server-tehtävä.
Jos luon palvelimen näin esimerkin mukaan:
Koodi:// luodaan palvelin porttiin 8080 ServerSocket server = new ServerSocket(8080); while (true) { // odotetaan pyyntöä Socket socket = server.accept(); // luetaan pyyntö Scanner lukija = new Scanner(socket.getInputStream()); // ... // kirjoitetaan vastaus PrintWriter kirjoittaja = new PrintWriter(socket.getOutputStream()); // ...
Ja tehtävän annossa on maininta: "Jos pyydetty polku on /quit, tulee palvelin sammuttaa."
Niin mistä löydän tuon polun?
Mietin tätä nyt vähän pidemmälle ja vaikuttaa siltä, että jonkinlainen linkkitaulu olisi hyvä olla. Jos nyt ymmärsin tämän oikein niin jos haluan tehdä TauluB:n tiedot sisältävän kyselyn TauluA:sta, niin tähän tarvitaan kaksi joinia: Ekalla joinilla joinataan linkkitauluAB TauluA:n kanssa ja toisella linkkitauluAB TauluB:n kanssa.Jos taulujen A ja B sisältö ei muuten muutu ajan mukaan (siis vuodesta/kuukaudesta/päivästä/jne riippuen) muuten kuin tuo viittaus B->A niin voit tehdä taulujen välille linkin jossa on vuosi.
Koodi:TauluA ( id Int, name String ) TauluB ( id Int, name String ) LinkkitauluAB ( tauluAId int, tauluBId int, vuosi int )
Linkkitauluun pitää sitten lisätä vuodesta riippuen oikeat arvot.
Yksi vaihtoehto on kopioida tarvittavat tiedot ajalla jne höystettynä erilliseen varastorakenteeseen josta otetaan tilastot.
SELECT
"TauluA"."id", "TauluA.name", "LinkkitauluAB"."vuosi", "TauluB"."id", "TauluB"."name"
FROM
"TauluA"
INNER JOIN "LinkkitauluAB" ON "TauluA"."id" = "LinkkitauluAB"."tauluAId"
INNER JOIN "TauluB" ON "LinkkitauluAB"."tauluBId" = "TauluB"."id"
WHERE
"linkkitauluAB"."vuosi" = 2021
Joo harjoituksen vuoksi pohdin näitä. Ehkä käytännön esimerkki auttaa ymmärtämään kysymyksen paremmin.Ymmärränköhän minäkään nyt ihan kaikkea tuosta kyssäristä, mutta siis jos taulu B viittaa taulun A johonkin riviin taulun A id:n perusteella, niin eikö taulussa A pitäisi olla silloin ylimääräisenä sarakkeena vuosi ja uniikit id:t eri vuosien riveille?
Jotenkin kuulostaa kovin hankalalta tuollaiset joinit ja linkkitaulut. Kuin myös natiivin SQL:n kirjoittelu koodissa näin tietämättä tarkemmin, mitä tässä toteutuksessa tehdäänSit jos tämän on tarkoituskin olla jonkinlainen SQL-harjoitus, niin asia eri.
Kauppa
id Int
nimi String
myynnissäOlevatTuotteet Tuote[]
Tuote
id Int
nimi String
myynnissäKaupassa Kauppa
Tuote
id Int
luontiaika DateTime
päättymisaika DateTime
nimi String
myynnissäKaupassa Kauppa
Tuote
id Int
luontiaika DateTime
päättymisaika DateTime
nimi String
myynnissäKaupassa Kauppa
myytyAsiakkaille Asiakas[]
Asiakas
id Int
nimi String
ostetutTuotteet Tuote[]
No tämähän on ihan klassinen many-to-many -relaatio tuotteiden ja kauppojen välillä. Se ratkeaa juuri linkitystaulun avulla, esim:Jos tässä tilanteessa haluan löytää Tuote-taulun kautta keille asiakkaille tuotetta on myyty kaupasta ja ajankohdasta riippumatta, niin kyselystä tulee monimutkaisempi, koska ensin täytyy yhdistää eri id:llä esiintyvät kuitenkin samat tuotteet "yhdeksi" ja sitten vasta hakea ne asiakastiedot.
TuoteKauppa
tuoteId
kauppaId
myynnissäAlk
myynnissäPäät
Joo, en edes lukenut niin tarkkaan että olisin nohin taulukoihin kiinnittänyt huomiota. Ei tosiaan ole normalisoitu rakenne tuo.Meikäläisen leipätyötä ei oo miettiä tietokantarakenteita, enkä väitä olevani mikään kova ammattilainen tietokantahommissa, mutta mietin tuossa jo aikaisemmin, että onko relaatiokanta oikea valinta tällaisille rakenteille.. Eikö esim. yhden sarakkeen arvon tule olla relaatiokannassa oppikirjamaisesti yksikäsitteinen? Nythän tuolla on sarakkeiden arvoina listoja, jotka nyt tietysti voi toteuttaa kooditasolla vaikka erotinmerkeillä varustettuina Stringeinä, mutta se ei liene oikein hyvää tapaa relaatiokantojen kanssa..
Ja jotenkin mulle tulis ekana mieleen käyttää jotain dokumenttitietokantaa tällaisessa, mutta en tokikaan kerennyt hirveästi pureskelemaan tämän tarvetta, kun tässä palaverin sivussa kirjoittelen
muoks. tai vaikka ei sotke tähän mitään dokumenttitietokantoja, niin voisi ainakin miettiä sitä, mikä tuollaisen kannan rakenne tulisi oikeasti olla.
Tuote (
id,
nimi
)
Kauppa (
id,
nimi
)
Asiakas (
id,
nimi,
email
)
Myynnissä (
kauppa_id,
tuote_id,
alkupvm,
loppupvm
)
Ostetut (
kauppa_id,
asiakas_id,
tuote_id
)
select <halutut sarakkeet>
from tuote t, ostetut o, asiakas a, kauppa k
where t.id = o.tuote_id
and o.asiakas_id = a.id
and o.kauppa_id = k.id
Kannattaa unohtaa listat jos tekee relaatiokannalla. Käytännössä listat muutetaan silloin riveiksi, yleensä omaan tauluun.
Joo tämän takia aloin miettimään parempaa ratkaisua. Joku ehdotti vuoden (alkuperäissä esimerkissä puhuttiin vuosista) tallentamista suoraan esimerkiksi tuote-tauluun, mutta se olisi aiheuttanut ongelmia duplikaattidatan ja monimutkaisempien kyselyjen muodossa.Hyvä periaate on se että tauluun ei laiteta sellaista tietoa joka monistaa rivejä, esimerkiksi tuotetauluun ei saa laittaa kauppaa koska silloin yksi tuote voi olla myynnissä vain yhdessä kaupassa. Sama koskee myynnin voimassaoloaikaa, se on tuote-kauppa- kohtainen.
Luontiaika ja muutosaika tuotteella voi olla.
select <halutut sarakkeet>
from tuote t, ostetut o, asiakas a, kauppa k
where t.id = o.tuote_id
and o.asiakas_id = a.id
and o.kauppa_id = k.id
Se sitä hain tuolla linkkitauluAB-esimerkilläni oli juuri tuo Zighin esittämä many-to-many-relaatio. Minulla oli siis päässäni jonkinlainen ratkaisu valmiina, mutta en tiennyt, että oliko se "oikea" tapa hoitaa homma.
Juu en osaa esittää oikein mitä ajan takaa. Hakasulkeilla en tarkoittanut listaa vaan koitin ilmaista, että kenttä sisältää useampia relaatioita (one-to-many-relaation one-puoli). Tämä syntaksi on käytössä ORMissa, jota käytän.
Joo tämän takia aloin miettimään parempaa ratkaisua. Joku ehdotti vuoden (alkuperäissä esimerkissä puhuttiin vuosista) tallentamista suoraan esimerkiksi tuote-tauluun, mutta se olisi aiheuttanut ongelmia duplikaattidatan ja monimutkaisempien kyselyjen muodossa.
En tiennytkään, että dataa voi valita selektiä käyttämällä useammasta taulukosta ilman joinia.Koodi:select <halutut sarakkeet> from tuote t, ostetut o, asiakas a, kauppa k where t.id = o.tuote_id and o.asiakas_id = a.id and o.kauppa_id = k.id
Lievä ot, minä kirjoitan SQL:n nykyään näin:Onhan tuossa join joka taulun välissä, syntaksi on vaan eri.
Select *
from a join b on a.i = b.i
where a.x = 1
Select *
from a, b
where a.i = b.i
and a.x = 1
Näissä toiminnallisuus on sama eri syntaksilla, ei ole väliä kumpaa käyttää paitsi jos mukana on outer join, silloin pitää olla tarkkana missä ehdot määritetään.
select
*
from
a
, b
where
a.i = b.i
and ax = 1
Lievä ot, minä kirjoitan SQL:n nykyään näin:
Näin saa helposti kommentoitua rivit mitä ei sillä hetkellä tarvitse.Koodi:select * from a , b where a.i = b.i and ax = 1
E: Ja nykyään olen opetellut käyttämään taulujen liitokseen from joinia. Se on osin selkeämpi jos tauluja on paljon ja että liitos tulee varmasti oikein eikä jää where lauseessa tekemättä.
SELECT "Player"."id", "Player"."lastName", SUM("GameStats"."goals") AS "goals"
FROM "Player"
INNER JOIN "GameStats" ON "Player"."id" = "GameStats"."playerId"
GROUP BY "Player"."id";
SQL-linjalla jatketaan. Mulla on tämä kysely:
SQL:SELECT "Player"."id", "Player"."lastName", SUM("GameStats"."goals") AS "goals" FROM "Player" INNER JOIN "GameStats" ON "Player"."id" = "GameStats"."playerId" GROUP BY "Player"."id";
Eli tuo kysely hakee kannasta kaikki pelaajat, joinaa pelaajatiedot pelikohtaisten tilastojen kanssa, summaa peleissä tehdyt maalit ja ryhmittää pelaajien mukaan. Mitäs jos en halua ottaa huomioon kaikkia pelejä vaan esimerkiksi vain 5 viimeisintä peliä? Oma veikkaus on, että tuon joinin jälkeen tarvitsisi jonkun WHERE-lausekkeen, mutta en keksi miten määritän ehdoksi "viisi viimeisintä riviä".
PostgreSQL-kanta.Millä perusteella haluat 5 viimeistä ?
Id- sekvenssi jonka mukaan otetaan 5 suurinta / aikaleima joista 5 viimeisintä / joku muu ?
Ja sitten vielä tärkeä, mikä kanta on alla ?
PostgreSQL-kanta.
Tosiaan, tuossa GameStats-taulukossa mulla ei ole suoraan tarvittavaa järjestystietoa. Mun pitäisi GameStats taulukko joinata ensin Game-taulukkoon, josta löytyy gameDate-tieto. Tuon gameDaten perusteella tarvitsisin viisi viimeisintä riviä GameStatseista.
SELECT
Player.id,
Player.lastName,
SUM(stats.goals) AS goals
FROM
Player INNER JOIN
(
SELECT
GameStats.playerId AS playerId,
GameStats.goals AS goals,
ROW_NUMBER() OVER (PARTITION BY GameStats.playerId ORDER BY Game.gameDate DESC) AS seqnum
FROM
Game JOIN GameStats ON (
Game.id = GameStats.gameId
)
) stats ON (
Player.id = stats.playerId
)
WHERE
stats.seqnum < 6
GROUP BY
Player.id,
Player.lastName
Kiitos! Toimii nätisti. Vähän vaikea ymmärtää amatöörille, mutta pala kerrallaan menee perille.En testannut mutta tähän tyyliin pitäisi onnistua
Koodi:SELECT Player.id, Player.lastName, SUM(stats.goals) AS goals FROM Player INNER JOIN ( SELECT GameStats.playerId AS playerId, GameStats.goals AS goals, ROW_NUMBER() OVER (PARTITION BY GameStats.playerId ORDER BY Game.gameDate DESC) AS seqnum FROM Game JOIN GameStats ON ( Game.id = GameStats.gameId ) ) stats ON ( Player.id = stats.playerId ) WHERE stats.seqnum < 6 GROUP BY Player.id, Player.lastName
Pikaselitys:
Sisemmässä kyselyssä haetaan playerid + goals ja samalla tehdään ikkun ointifunktiolla kasvava järjestysnumero per playerid.
Ulommassa ulommassa kyselyssä yhdistetään sisemmän tulokseen player (= rivimäärä ei muutu) ja rajataan ikkunoinnin luoma rivinumero < 6 ja summataan goals.
Testaa kannassa ensin sisempi erikseen että saat oikeanlaisen tuloksen ja sen jälkeen yhdistelmä.
SELECT "CumulativeStats"."id" AS "playerId", "CumulativeStats"."lastName", SUM(goals) AS "goals" FROM (
SELECT "Player"."id", "Player"."lastName", "Game"."gameDate", "GameStats"."goals"
FROM "Player"
INNER JOIN "GameStats" ON "Player"."id" = "GameStats"."playerId"
INNER JOIN "Game" ON "GameStats"."gameId" = "Game"."id"
) AS "CumulativeStats"
GROUP BY "playerId", "lastName";
Kiitos! Toimii nätisti. Vähän vaikea ymmärtää amatöörille, mutta pala kerrallaan menee perille.
Itse pääsin omin päin tähän asti:
Tuosta tosiaan puuttuu juuri se tärkein eli miten ottaa huomioon vain 5 viimeisintä peliä.SQL:SELECT "CumulativeStats"."id" AS "playerId", "CumulativeStats"."lastName", SUM(goals) AS "goals" FROM ( SELECT "Player"."id", "Player"."lastName", "Game"."gameDate", "GameStats"."goals" FROM "Player" INNER JOIN "GameStats" ON "Player"."id" = "GameStats"."playerId" INNER JOIN "Game" ON "GameStats"."gameId" = "Game"."id" ) AS "CumulativeStats" GROUP BY "playerId", "lastName";
SELECT
"Player"."id",
"Team"."name",
SUM("Stats"."goals") AS "goals",
SUM("Stats"."assists") AS "assists"
FROM
"Player" INNER JOIN
(
SELECT
"GameStats"."playerId" AS "playerId",
"GameStats"."goals" AS "goals",
"GameStats"."assists" AS "assists",
ROW_NUMBER() OVER (PARTITION BY "GameStats"."playerId" ORDER BY "Game"."gameDate" DESC) AS "seqnum"
FROM
"Game" JOIN "GameStats" ON (
"Game"."id" = "GameStats"."gameId"
)
) "Stats" ON (
"Player"."id" = "Stats"."playerId"
)
JOIN "PlayerTeam" ON "Player"."id" = "PlayerTeam"."playerId"
JOIN "Team" ON "PlayerTeam"."teamId" = "Team"."id"
WHERE
"Stats"."seqnum" < 6 AND
"PlayerTeam"."endDate" IS NOT NULL
GROUP BY
"Player"."id",
"Team"."name"
Lisäsin tuohon vielä jokaiselle riville pelaajan nykyisen tiimin nimen. Hakuaikaa tuli yli tuplat lisää. Meniköhän joku väärin? Ilman tiimiä hakuaika on 0,5s ja tiimin kanssa 1,3s.
Tässä ratkaisuni:
SQL:SELECT "Player"."id", "Team"."name", SUM("Stats"."goals") AS "goals", SUM("Stats"."assists") AS "assists" FROM "Player" INNER JOIN ( SELECT "GameStats"."playerId" AS "playerId", "GameStats"."goals" AS "goals", "GameStats"."assists" AS "assists", ROW_NUMBER() OVER (PARTITION BY "GameStats"."playerId" ORDER BY "Game"."gameDate" DESC) AS "seqnum" FROM "Game" JOIN "GameStats" ON ( "Game"."id" = "GameStats"."gameId" ) ) "Stats" ON ( "Player"."id" = "Stats"."playerId" ) JOIN "PlayerTeam" ON "Player"."id" = "PlayerTeam"."playerId" JOIN "Team" ON "PlayerTeam"."teamId" = "Team"."id" WHERE "Stats"."seqnum" < 6 AND "PlayerTeam"."endDate" IS NOT NULL GROUP BY "Player"."id", "Team"."name"
Mulla on siis PlayerTeam-niminen taulukko, jossa on viittauksen kaikkiin pelaajien aikaisempiin tiimeihin ja nykyinen tiimi on se rivi, jossa endDate on NULL. Tässä on sellainen ongelma, että nyt käsittääkseni jokaisen pelaajan tilastot jakautuu joukkueiden mukaan, mutta tämä ei ole haluttua. Haluaisin tehdä niin, GROUP BY:ssä lasketaan kaikki tilastot tiettyjen pelien osalta yhteen ja vasta sen jälkeen lisätään hakutulokseen muu "metadata", kuten esimerkiksi juuri tuo tiimi ja kaikki muu Player-taulukosta löytyvä data.
En nyt jaksa tarkistaa, kun on muutenkin omasta mielestäni hyvä arvaus, mutta siis näin: Ctrl + F hakee useimmissa ohjelmissa vain auki olevasta tiedostosta, kun taas Ctrl + Shift + F hakee kaikista projektin tms. tiedostoista. Sinulla kuulostaa siis olevan liian suppea haku käytössä.Olen C# aloittelija. Miksi en löydä projektista (vai solutionista?) tiettyä muuttujaa Visual Studio 2019 Community:llä?
Tarkoitukseni oli muuttaa muuttujan VeryLow.DistanceFromTakeOffLocation arvo käsin:
1. Kloonasinsuoraan VS2019:llä![]()
akaAgar/briefing-room-for-dcs
An advanced mission generator for Eagle Dynamic's DCS World. - akaAgar/briefing-room-for-dcsgithub.com
2. Avasin VS2019:llä Source/BriefingRoom.sln (kokeilin myös Source/BriefingRoom.csproj)
3. Ctrl+f ja hakukenttään VeryLow.DistanceFromTakeOffLocation
4. Ei löydy!?
Hämmentyneenä etsin sen sitten käsin ja se löytyi Database/Objectives.ini:stä. Miksi VS2019 ei etsinyt myös tuolta Database-hakemistosta? Sitä ei tosin näy VS:n puolella Solution Explorerissa, eli nuin kai sen pitäisikin toimia, mutta hämää paljon kun se silti tuli gitistä samaan syssyyn ja lukeehan se ohjelmakin tuota tiedostoa!?
Olen C# aloittelija. Miksi en löydä projektista (vai solutionista?) tiettyä muuttujaa Visual Studio 2019 Community:llä?
enä etsin sen sitten käsin ja se löytyi Database/Objectives.ini:stä. Miksi VS2019 ei etsinyt myös tuolta Database-hakemistosta? Sitä ei tosin näy VS:n puolella Solution Explorerissa, eli nuin kai sen pitäisikin toimia, mutta hämää paljon kun se silti tuli gitistä samaan syssyyn ja lukeehan se ohjelmakin tuota tiedostoa!?
Miltäs tämä näyttää:Tulee hidas siksi että tiimit lisätään ennen summausta. Lisäksi jos nykyisellä tiimillä enddate on null niin tuolla yllä olevalla saat kaikki muut paitsi nykyisen.
Eli jos ymmärsin oikein niin enddate is null olisi oikea ehto, silloin joinin ei pitäisi lisätä rivimäärää olettaen että voi kuulua kerrallaan vain yhteen tiimiin.
Saattaa toimia silti paremmin niin että pidät alkuperäisen kyselyn ennallaan (summat pelaajittain) ja liität sen kylkeen muut tiedot jolloin ruvejä on enää 1 per pelaaja.
Jos rivejä on paljon niin join ja ehtosarakkeille kannattaa tehdä indeksit.
Samoin jos sisäkkäisiä kyselyjä tulee paljon niin näkymät auttavat, ei tehossa mutta selkeyttää.
SELECT
"Player"."id",
"Player"."lastName",
"Team"."name",
"PlayerStats"."goals",
"PlayerStats"."assists"
FROM
(
SELECT
"Player"."id",
SUM("Stats"."goals") AS "goals",
SUM("Stats"."assists") AS "assists"
FROM
"Player"
INNER JOIN (
SELECT
"GameStats"."playerId" AS "playerId",
"GameStats"."goals" AS "goals",
"GameStats"."assists" AS "assists",
ROW_NUMBER() OVER (
PARTITION BY "GameStats"."playerId"
ORDER BY
"Game"."gameDate" DESC
) AS "seqnum"
FROM
"Game"
JOIN "GameStats" ON (
"Game"."id" = "GameStats"."gameId"
)
) "Stats" ON (
"Player"."id" = "Stats"."playerId"
)
WHERE
"Stats"."seqnum" < 6
GROUP BY
"Player"."id"
) AS "PlayerStats"
JOIN "Player" ON "PlayerStats"."id" = "Player"."id"
JOIN "PlayerTeam" ON "Player"."id" = "PlayerTeam"."playerId"
JOIN "Team" ON "PlayerTeam"."teamId" = "Team"."id"
WHERE
"PlayerTeam"."endDate" IS NULL
Käytämme välttämättömiä evästeitä, jotta tämä sivusto toimisi, ja valinnaisia evästeitä käyttökokemuksesi parantamiseksi.