Поменять местами столбцы в PostgreSQL 04
16
Обмен столбцами таблицы SQL является частью стандартного репертуара MySQL — это (пока) не поддерживается в PostgreSQL. Хотя официальная вики посвящает проблеме отдельную статью , в ней не показано практического решения, которое также поддерживает представления, индексы и триггеры. Следующий класс выполняет эту работу (как для MySQL, так и для PostgreSQL) либо в командной строке, либо непосредственно в Laravel 5.
public static function getQuotes() < if (getenv("DB_CONNECTION") == "pgsql") < return ""; >if (getenv("DB_CONNECTION") == "mysql") < return "`"; >> public static function getPath() < if (getenv("DB_CONNECTION") == "pgsql") < $sql = new \PDO('pgsql:host=' . getenv('DB_HOST') . ';port=' . getenv('DB_PORT') . ';dbname=' . getenv('DB_DATABASE') , getenv('DB_USERNAME') , getenv('DB_PASSWORD')); $stmt = $sql->prepare("SHOW data_directory"); $stmt->execute(); $path = str_replace("data", "bin", $stmt->fetchObject()->data_directory) . "/"; > if (getenv("DB_CONNECTION") == "mysql") < $sql = new \PDO('mysql:host=' . getenv('DB_HOST') . ';port=' . getenv('DB_PORT') . ';dbname=' . getenv('DB_DATABASE') , getenv('DB_USERNAME') , getenv('DB_PASSWORD')); $stmt = $sql->prepare("SHOW VARIABLES LIKE 'basedir'"); $stmt->execute(); $path = $stmt->fetchObject()->Value . "bin/"; > return $path; > public static function exportDB() < if (getenv("DB_CONNECTION") == "pgsql") < putenv("PGPASSWORD=" . getenv('DB_PASSWORD')); exec('"' . self::$path . 'pg_dump" --clean --inserts -h ' . getenv('DB_HOST') . ' -p ' . getenv('DB_PORT') . ' -U ' . getenv('DB_USERNAME') . ' ' . getenv('DB_DATABASE') . ' >db.sql'); > if (getenv("DB_CONNECTION") == "mysql") < exec('"' . self::$path . 'mysqldump" -h ' . getenv('DB_HOST') . ' --port ' . getenv('DB_PORT') . ' -u ' . getenv('DB_USERNAME') . ' -p"' . getenv('DB_PASSWORD') . '" ' . getenv('DB_DATABASE') . ' >db.sql'); > return file_get_contents("db.sql"); > public static function importDB($content) < file_put_contents("db.sql", $content); if (getenv("DB_CONNECTION") == "pgsql") < putenv("PGPASSWORD=" . getenv('DB_PASSWORD')); exec('"' . self::$path . 'psql" -h ' . getenv('DB_HOST') . ' -p ' . getenv('DB_PORT') . ' -U ' . getenv('DB_USERNAME') . ' -d ' . getenv('DB_DATABASE') . ' -1 -f db.sql'); >if (getenv("DB_CONNECTION") == "mysql") < exec('"' . self::$path . 'mysql" -h ' . getenv('DB_HOST') . ' --port ' . getenv('DB_PORT') . ' -u ' . getenv('DB_USERNAME') . ' -p"' . getenv('DB_PASSWORD') . '" ' . getenv('DB_DATABASE') . ' --default-character-set=utf8 < db.sql'); >unlink("db.sql"); > public static function getPositions($haystack, $needle) < $positions = []; $lastPos = 0; while (($lastPos = strpos($haystack, $needle, $lastPos)) !== false) < $positions[] = $lastPos; $lastPos = $lastPos + strlen($needle); >return $positions; > public static function getEnd($content, $begin) < $end = $begin; $outside = true; while ($outside !== true || $content[$end] != ";") < if ($content[$end] == "'") < if ($end === 0 || $content[$end - 1] != "\\") < $outside = !$outside; >> $end++; > return ++$end; > public static function splitString($string) < return preg_split('/(?public static function getColumns($query) < $i = 0; $outside = true; $query = self::splitString($query); foreach($query as $i =>$char) < if ($query[$i] == "'") < if ($i === 0 || $query[$i - 1] != "\\") < $outside = !$outside; >> if ($outside === true && $query[$i] == ",") < $query[$i] = "♥"; >$i++; > $query = implode("", $query); $cols = explode("♥", $query); return $cols; > public static function swapNow($table, $col1, $col2, $content) < // loop through relevant statements foreach(["CREATE TABLE " . self::$quotes . $table . self::$quotes, "INSERT INTO " . self::$quotes . $table . self::$quotes] as $skey =>$statement) < $positions = self::getPositions($content, $statement); foreach($positions as $position) < $begin = $position; $end = self::getEnd($content, $begin); $query_all = substr($content, $begin, $end - $begin); $query_inside = substr($query_all, strpos($query_all, "(") + 1, strrpos($query_all, ")") - strpos($query_all, "(") - 1); // get columns $cols = self::getColumns($query_inside); // get relevant column indexes if ($skey == 0) < $col1pos = 0; $col2pos = 0; foreach($cols as $pos =>$col) < $col = trim($col); if (strpos($col, self::$quotes . $col1 . self::$quotes) === 0) < $col1pos = $pos; >if (strpos($col, self::$quotes . $col2 . self::$quotes) === 0) < $col2pos = $pos; >> > // swap columns $tmp = $cols[$col1pos]; $cols[$col1pos] = $cols[$col2pos]; $cols[$col2pos] = $tmp; $query_inside_new = implode(",", $cols); // insert query into content $query_all_new = str_replace($query_inside, $query_inside_new, $query_all); $content = str_replace($query_all, $query_all_new, $content); > > return $content; > > // usage from the command line if (isset($argv) && is_array($argv)) < $args = []; foreach($argv as $key =>$arg) < switch ($arg) < case "-e": $args["engine"] = $argv[$key + 1]; break; case "-h": $args["hostname"] = $argv[$key + 1]; break; case "-P": $args["port"] = $argv[$key + 1]; break; case "-u": $args["username"] = $argv[$key + 1]; break; case "-p": $args["password"] = $argv[$key + 1]; break; case "-d": $args["database"] = $argv[$key + 1]; break; case "-t": $args["table"] = $argv[$key + 1]; break; >> // set default values if (!isset($args["hostname"])) < $args["hostname"] = "127.0.0.1"; >if (!isset($args["port"]) && isset($args["engine"]) && $args["engine"] == "mysql") < $args["port"] = "3306"; >if (!isset($args["port"]) && isset($args["engine"]) && $args["engine"] == "pgsql") < $args["port"] = "5432"; >foreach($args as $option => $arg) < if (!isset($arg)) < die('missing option ' . $option); >> if (count($argv) < 2) < die('error'); >$args["col1"] = $argv[count($argv) - 2]; $args["col2"] = $argv[count($argv) - 1]; putenv("DB_CONNECTION=" . $args["engine"]); putenv("DB_HOST=" . $args["hostname"]); putenv("DB_PORT=" . $args["port"]); putenv("DB_DATABASE=" . $args["database"]); putenv("DB_USERNAME=" . $args["username"]); putenv("DB_PASSWORD=" . $args["password"]); ColumnChanger::swap($args["table"], $args["col1"], $args["col2"]); >
Вызов командной строки не требует пояснений:
php ColumnChanger.php -e pgsql -h 127.0.0.1 -P 5432 -u username -p password -d database -t table col1 col2 php ColumnChanger.php -e mysql -h 127.0.0.1 -P 3306 -u username -p password -d database -t table col1 col2
Интеграция в Laravel 5 также выполняется быстро, просто скопировав ColumnChanger.php в папку app / Helpers. Затем вы можете менять местами столбцы прямо в миграциях.:
/** * Reverse the migrations. * * @return void */ public function down() < App\Helpers\ColumnChanger::swap("users","password","email"); >>
Адрес офиса
close2 new media GmbH
Auenstrasse 6
80469 Мюнхен
SQL. поменять строки и столбы местами с помощью VIEW

Всем привет. Имеется 2 таблицы. Нужно перейти из одной в другую и наоборот. Используя VIEW или виртуальные таблицы. Буду благодарен за совет.
Отслеживать
задан 31 янв 2021 в 19:34
Ponoptikum Ponoptikum
15 3 3 бронзовых знака
А какой диалект?
31 янв 2021 в 19:36
честно, не понял про диалект,
31 янв 2021 в 19:39
но видно, что нужно развернуть таблицу. строки в столбы и наоборот
31 янв 2021 в 19:39
пробую пока через WITH решить, но пока не очень
31 янв 2021 в 19:42
ну вот есть ms-sql, есть mysql, есть oracle, есть postgresql, у вас что?
31 янв 2021 в 19:52
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
select a.student, b.* from result_table_1 a cross join lateral ( values (a.h, 'H'), (a.z, 'Z'), (a.e, 'E') ) as b(atyp, prozent) order by student, atyp;
Отслеживать
ответ дан 1 фев 2021 в 1:07
Aziz Umarov Aziz Umarov
22.5k 2 2 золотых знака 10 10 серебряных знаков 33 33 бронзовых знака
да, это работает, спасибо
1 фев 2021 в 13:59
@Ponoptikum Ессли ответ помог то можете пометить как полезный под стрелками
1 фев 2021 в 14:06
-
Важное на Мете
Похожие
Подписаться на ленту
Лента вопроса
Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.
Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.11.15.1019
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
Поменять строки местами
В одной таблице поменять местами строки
На примере думаю нагляднее будет, что мне надо — вот смотрите есть таблица (NameList) в ней всего 2.
Поменять местами первый и последний столбец, после поменять местами первый и предпоследний строки
Масив 4х4, нужно поменять местами первый и последний столбец, после поменять местами первый и.

У матрицы с размером M*N поменять местами строки с наибольшим и наименьшим элементом местами
Всем привет, подскажите пожалуйста. Как в Windows Form у матрицы с размером M*N поменять местами.
91 / 56 / 12
Регистрация: 02.10.2008
Сообщений: 550
поменять на что? Конкретнее опешите задачу
1312 / 944 / 144
Регистрация: 17.01.2013
Сообщений: 2,348
Регистрация: 07.12.2012
Сообщений: 126
поменять местами строки, если id первичный
63 / 63 / 21
Регистрация: 08.02.2013
Сообщений: 262
Это не таблица, это выборка из 2-ух таблиц
а в выборке порядок меняется с помощью ORDER BY
Регистрация: 07.12.2012
Сообщений: 126
мне сказали что order by не нужно, нужно создать команду при нажатии кнопки два select и два update
2509 / 1130 / 582
Регистрация: 07.06.2014
Сообщений: 3,286
Сообщение от Radmir71 
мне сказали что order by не нужно
я бы на вашем месте этим советчикам не доверял, фигню они Вам советуют.
в реляционных СУБД записи НЕ ИМЕЮТ физического порядка, нельзя сказать, что запись с кодом 1 расположена до записи с кодом 3, например!
И если не использован ORDER BY в запросе, записи МОГУТ быть расположены в ПРОИЗВОЛЬНОМ порядке!
(да, современные мощные СУБД используют внутренние механизмы, которые ЧАЩЕ всего возвращают набор записей в определённом порядке. но поймите, что делать они это НЕ ОБЯЗАНЫ)
Успехов Вам в осознании того факта, что порядок записей в выборке определяется исключетльно через ORDER BY и никак иначе!
Как поменять строки местами в sql
В результате запросо нужно получить:
C R L
1 7 8
Те поменять строки и столбцы местами.
Как сделать такой запрос?
← →
unknown © ( 2006-11-10 15:18 ) [1]
Нормально — никак.
Только подзапросами :
select
(select .. from..) as «C»,
(select .. from..) as «R»,
(select .. from..) as «L»
from .
Если же еще и количество столбцов м.б. не известно
(динамически формируется запрос), то придется
пересмотреть логику.
Если все это для отображения на клиенте — ищи CrossTab
компоненты.
← →
Anatoly Podgoretsky © ( 2006-11-10 15:42 ) [2]
> Kolan (10.11.2006 15:05:00) [0]
Где, в некоторых местах просто, в других надо потрудиться
← →
Desdechado © ( 2006-11-10 16:09 ) [3]
Если это просто для отображения, то искать на королевстве делфи nxdbgrid
← →
Kolan © ( 2006-11-10 19:01 ) [4]
Вот зачем мне это надо:
http://delphimaster.net/view/3-1161622321/
Так вот мне пользователю надо паказывать измерение так:
Номер, Дата, Кто проводил, и параметры в виде R, L, C, Ct и так далее(те в строчку. )
← →
Kolan © ( 2006-11-11 16:07 ) [5]
Так что идей нет? Или это невозможно?
← →
sniknik © ( 2006-11-11 16:55 ) [6]
гдето просто, гдето потрудится. [2].
← →
evvcom © ( 2006-11-13 09:28 ) [7]
> [4] Kolan © (10.11.06 19:01)
Лучше нафиг так не делай. Сделай простейшее дерево и TreeList-ом отображай. В корне
> Номер, Дата, Кто проводил
а в листьях
> параметры в виде R, L, C, Ct и так далее
но для каждого своя строка. Имхо.
← →
Stanislav © ( 2006-11-13 10:39 ) [8]
На MS SQL примерно делается так:
Select
C=Case when name=»C» then max(value) else Null end
R=Case when name=»R» then max(value) else Null end
from table
group by name
← →
Kolan © ( 2006-11-13 12:12 ) [9]
> но для каждого своя строка. Имхо.
Нет это негодится.. Таких записей много. Одна строчка-одно измерение.
> Stanislav © (13.11.06 10:39)
Не очень понял..
Params
MeasurmentID ParamID ParamValue
1 1 10.0
1 2 20.0
1 3 33.0
ParamsDictionary
ParamID ParamName
1 R
2 L
3 C
Вот запрос:
SELECT Params.MeasurmentID, ParamsDictionary.ParamName, Params.ParamValue FROM
Params, ParamsDictionary
WHERE
Params.ParamID = ParamsDictionary.ParamID
Получаю:
№ ParamName Value
1 R 10.0
1 L 20.0
1 C 33.0
А нужно так:
№ R L C
1 10.0 20.0 33.0
← →
Kolan © ( 2006-11-13 12:16 ) [11]
Черт, все испртилось 🙁 Понятно? Или еще раз запостить?
← →
Stanislav © ( 2006-11-13 12:18 ) [12]
Так и будет, если у тебя MS SQL.
← →
Stanislav © ( 2006-11-13 12:20 ) [13]
Только в Group by нужно № поставить.
← →
Kolan © ( 2006-11-13 12:20 ) [14]
> [12] Stanislav © (13.11.06 12:18)
> Так и будет, если у тебя MS SQL.
Это ты T-Sql использовал? Без него никак?
И к тому же тут жестко заданы имена, а их надо выбрать из Словоря.
C=Case when name=«C» then max(value) else Null end
← →
Kolan © ( 2006-11-13 12:25 ) [15]
Попробовал.. Не получилос. Напиши с моими именами полей и таблиц
Я сдела так:
Select
C=Case when name=»C» then max(value) else Null end
R=Case when name=»R» then max(value) else Null end
from Params
group by MeasurmentID
Получил ошибку:
Line 18: Incorrect syntax near «R».
← →
Stanislav © ( 2006-11-13 12:27 ) [16]
Это чистый SQL.
Есть хранимка, но она не работает с большим кол-вом столбцов. если надо опубликую, но там уже T-SQL.
Если Акцесс там встроеный оператор есть.
← →
Stanislav © ( 2006-11-13 12:28 ) [17]
Запятая нужна
C=Case when name=»C» then max(value) else Null end,
← →
Kolan © ( 2006-11-13 12:32 ) [18]
Неполучается 🙁
Запутался. name=»C» — это что за имя? Из какой таблицы?
← →
ЮЮ © ( 2006-11-13 12:33 ) [19]
Ты сам пошел этим путем.
Если в каждом измерении есть R, L, и С, то и стоило их делать атрибутами сущности Измерения.
> А нужно так:
> № R L C
> 1 10.0 20.0 33.0
Тогда забудь о простых запросах:
SELECT
pr.MeasurmentID, pR.Value R, pC.Value C, pL.Value L
FROM
(SELECT * FROM Params WHERE ParamID = 1) pR
LEFT JOIN (SELECT * FROM Params WHERE ParamID = 2) pC ON
pr.MeasurmentID = pC.MeasurmentID
LEFT JOIN (SELECT * FROM Params WHERE ParamID = 3) pL ON
pr.MeasurmentID = pL.MeasurmentID
← →
Kolan © ( 2006-11-13 12:38 ) [20]
> Если в каждом измерении есть R, L, и С, то и стоило их делать
> атрибутами сущности Измерения.
В том все и дело, что параметров — н штук, поэтому и сделал соварь отдельно.
Запрос понял, получилось.. Осталось одно но 🙂
Как сделать для неизвестного числа параметров?
← →
Kolan © ( 2006-11-13 12:39 ) [21]
И к томуже имена опять вручную, а если пользоваетль изменит L на Ln.
← →
ЮЮ © ( 2006-11-13 12:44 ) [22]
> Как сделать для неизвестного числа параметров?
Динамически! Научи программу написать подобный запрос, основываясь на таблице ParamsDictionary
← →
Kolan © ( 2006-11-13 12:47 ) [23]
> [22] ЮЮ © (13.11.06 12:44)
>
> > Как сделать для неизвестного числа параметров?
>
>
> Динамически! Научи программу написать подобный запрос, основываясь
> на таблице ParamsDictionary
Понял. Думал это все база делает 🙂
← →
Stanislav © ( 2006-11-13 13:01 ) [24]
Вот хранимка для динамического построения, честно говоря сам ей не пользуюсь — неудобно, все делаю компонентами отображения.
CREATE PROC sp_CrossW
@table AS sysname,
@onrows AS nvarchar(256),
@onrowsalias AS sysname = NULL,
@oncols AS nvarchar(256),
@sumcol AS sysname = NULL ,
@Condition as nvarchar (256)
AS
DECLARE
@sql AS nvarchar (4000),
@NEWLINE AS char(1)
SET @NEWLINE = CHAR(10)
SET @sql =
«SELECT» + @NEWLINE +
» » + @onrows +
CASE
WHEN @onrowsalias IS NOT NULL THEN » AS » + @onrowsalias
ELSE «»
END
CREATE TABLE #keys(keyvalue nvarchar(100) NOT NULL PRIMARY KEY)
DECLARE @keyssql AS varchar(1000)
SET @keyssql =
«INSERT INTO #keys » +
«SELECT DISTINCT CAST(» +@oncols + » AS nvarchar(100)) » +
«FROM » + @table
DECLARE @key AS nvarchar(100)
SELECT @key = MIN(keyvalue) FROM #keys
WHILE @key IS NOT NULL
BEGIN
SET @sql = @sql + «,» + @NEWLINE +
» MAX(CASE CAST(» + @oncols +
» AS NVARCHAR(100))» + @NEWLINE +
» WHEN N»»» + @key +
«»» THEN » + @sumcol+ @NEWLINE +
» ELSE NULL» + @NEWLINE +
» END) AS [» + @key+»]»
SELECT @key = MIN(keyvalue) FROM #keys
WHERE keyvalue > @key
END
SET @sql = @sql + @NEWLINE +
«FROM » + @table + @NEWLINE +
@condition+@NEWLINE+
«GROUP BY » + @onrows + @NEWLINE +
«ORDER BY » + @onrows
PRINT @sql + @NEWLINE
EXEC (@sql)
GO
← →
Kolan © ( 2006-11-13 13:05 ) [25]
Убил, я еще не дорос до этого 🙁
Лана, пойду у препода спрошу мож он обяснить.
А как ты средаствами отображения это делаешь?
← →
Stanislav © ( 2006-11-13 13:24 ) [26]
Отчеты в Excel Через сводную таблицу.
В FastReport мучатся долго нужно.
А хранимку текст скопируй в QA и выполни, потом вызывать ее так:
sp_CrossW
@table = «MyTable»,
@onrows = «№» — в твоем случае
@oncols = «NAME»
@sumcol = «Value»
@Condition = «where . «, можно «»
← →
atruhin © ( 2006-11-13 15:52 ) [27]
> В FastReport мучатся долго нужно.
Ну ну целый компонент CrossTab на форму кинуть ! 🙂
← →
Stanislav © ( 2006-11-13 16:21 ) [28]
atruhin © (13.11.06 15:52) [27]
Он тормозит, к тому же есть много ограничений.
← →
имя ( 2006-11-13 17:19 ) [29]
Удалено модератором
← →
Alex’ ( 2006-11-14 11:47 ) [30]
В MS SQL 2005 TSQL появились ф-ии PIVOT и UNPIVOT
запрос будет выглядеть примерно:
SELECT [С], [L], [R] FROM MyTable PIVOT (SUM(Value) FOR [Name] IN ([C], [L], [R])) AS PVT
Непроверял, взято http://www.citforum.ru/database/articles/tsql_mssql/
← →
ЮЮ © ( 2006-11-14 12:09 ) [31]
к [19]
Кстати, можно и не join-ить таблицу многократно, а использовать case в select:
SELECT MeasurmentID,
SUM(CASE ParamID WHEN 1 THEN Value ELSE 0 END) AS R,
SUM(CASE ParamID WHEN 2 THEN Value ELSE 0 END) AS C,
SUM(CASE ParamID WHEN 3 THEN Value ELSE 0 END) AS L
FROM Params
GROUP BY MeasurmentID
← →
Stanislav © ( 2006-11-14 14:49 ) [32]
Alex» (14.11.06 11:47) [30]
Классная штука, я использую, только динамически все равно не получиться.
← →
Kolan © ( 2006-11-16 11:47 ) [33]
Это ппц. Справился 🙂 Понадобилось 3 чрон процедуры сделать, создать таблицу и View все динамически.